1 /* glbl.c - this module holds global defintions and data items.
2  * These are shared among the runtime library. Their use should be
3  * limited to cases where it is actually needed. The main intension for
4  * implementing them was support for the transistion from v2 to v4
5  * (with fully modular design), but it turned out that there may also
6  * be some other good use cases besides backwards-compatibility.
7  *
8  * Module begun 2008-04-16 by Rainer Gerhards
9  *
10  * Copyright 2008-2021 Rainer Gerhards and Adiscon GmbH.
11  *
12  * This file is part of the rsyslog runtime library.
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *       http://www.apache.org/licenses/LICENSE-2.0
19  *       -or-
20  *       see COPYING.ASL20 in the source distribution
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an "AS IS" BASIS,
24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "config.h"
30 #include <stdlib.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/wait.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <pthread.h>
38 #include <ctype.h>
39 #include <assert.h>
40 #include <stdint.h>
41 #include <errno.h>
42 
43 #include "rsyslog.h"
44 #include "obj.h"
45 #include "unicode-helper.h"
46 #include "cfsysline.h"
47 #include "glbl.h"
48 #include "prop.h"
49 #include "atomic.h"
50 #include "errmsg.h"
51 #include "action.h"
52 #include "parserif.h"
53 #include "rainerscript.h"
54 #include "srUtils.h"
55 #include "operatingstate.h"
56 #include "net.h"
57 #include "rsconf.h"
58 #include "queue.h"
59 #include "dnscache.h"
60 #include "parser.h"
61 
62 #define REPORT_CHILD_PROCESS_EXITS_NONE 0
63 #define REPORT_CHILD_PROCESS_EXITS_ERRORS 1
64 #define REPORT_CHILD_PROCESS_EXITS_ALL 2
65 
66 /* some defaults */
67 #ifndef DFLT_NETSTRM_DRVR
68 #	define DFLT_NETSTRM_DRVR ((uchar*)"ptcp")
69 #endif
70 
71 /* static data */
72 DEFobjStaticHelpers
73 DEFobjCurrIf(prop)
74 DEFobjCurrIf(net)
75 
76 /* static data
77  * For this object, these variables are obviously what makes the "meat" of the
78  * class...
79  */
80 int glblDebugOnShutdown = 0;	/* start debug log when we are shut down */
81 #ifdef ENABLE_LIBLOGGING_STDLOG
82 stdlog_channel_t stdlog_hdl = NULL;	/* handle to be used for stdlog */
83 #endif
84 
85 static struct cnfobj *mainqCnfObj = NULL;/* main queue object, to be used later in startup sequence */
86 #ifndef DFLT_INT_MSGS_SEV_FILTER
87 	#define DFLT_INT_MSGS_SEV_FILTER 6	/* Warning level and more important */
88 #endif
89 int glblIntMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER;/* filter for logging internal messages by syslog sev. */
90 int bProcessInternalMessages = 0;	/* Should rsyslog itself process internal messages?
91 					 * 1 - yes
92 					 * 0 - send them to libstdlog (e.g. to push to journal) or syslog()
93 					 */
94 static uchar *pszWorkDir = NULL;
95 #ifdef ENABLE_LIBLOGGING_STDLOG
96 static uchar *stdlog_chanspec = NULL;
97 #endif
98 static int bParseHOSTNAMEandTAG = 1;	/* parser modification (based on startup params!) */
99 static int bPreserveFQDN = 0;		/* should FQDNs always be preserved? */
100 static int iMaxLine = 8096;		/* maximum length of a syslog message */
101 static uchar * oversizeMsgErrorFile = NULL;		/* File where oversize messages are written to */
102 static int oversizeMsgInputMode = 0;	/* Mode which oversize messages will be forwarded */
103 static int reportOversizeMsg = 1;	/* shall error messages be generated for oversize messages? */
104 static int reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
105 static int iGnuTLSLoglevel = 0;		/* Sets GNUTLS Debug Level */
106 static int iDefPFFamily = PF_UNSPEC;     /* protocol family (IPv4, IPv6 or both) */
107 static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
108 static int option_DisallowWarning = 1;	/* complain if message from disallowed sender is received */
109 static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */
110 static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */
111 static int propLocalIPIF_set = 0;	/* is propLocalIPIF already set? */
112 static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
113 static prop_t *propLocalHostNameToDelete = NULL;/* see GenerateLocalHostName function hdr comment! */
114 static uchar *LocalHostName = NULL;/* our hostname  - read-only after startup, except HUP */
115 static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */
116 static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */
117 static uchar *LocalDomain = NULL;/* our local domain name  - read-only after startup, except HUP */
118 static char **StripDomains = NULL;
119 /* these domains may be stripped before writing logs  - r/o after s.u., never touched by init */
120 static char **LocalHosts = NULL;
121 /* these hosts are logged with their hostname  - read-only after startup, never touched by init */
122 static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream driver */
123 static uchar *pszDfltNetstrmDrvrCAF = NULL; /* default CA file for the netstrm driver */
124 static uchar *pszDfltNetstrmDrvrKeyFile = NULL; /* default key file for the netstrm driver (server) */
125 static uchar *pszDfltNetstrmDrvrCertFile = NULL; /* default cert file for the netstrm driver (server) */
126 int bTerminateInputs = 0;		/* global switch that inputs shall terminate ASAP (1=> terminate) */
127 static uchar cCCEscapeChar = '#'; /* character to be used to start an escape sequence for control chars */
128 static int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
129 static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
130 static int bSpaceLFOnRcv = 0; /* replace newlines with spaces on reception: 0 - no, 1 - yes */
131 static int bEscape8BitChars = 0; /* escape characters > 127 on reception: 0 - no, 1 - yes */
132 static int bEscapeTab = 1; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */
133 static int bParserEscapeCCCStyle = 0; /* escape control characters in c style: 0 - no, 1 - yes */
134 short janitorInterval = 10; /* interval (in minutes) at which the janitor runs */
135 int glblReportNewSenders = 0;
136 int glblReportGoneAwaySenders = 0;
137 int glblSenderStatsTimeout = 12 * 60 * 60; /* 12 hr timeout for senders */
138 int glblSenderKeepTrack = 0;  /* keep track of known senders? */
139 int glblUnloadModules = 1;
140 int bPermitSlashInProgramname = 0;
141 int glblIntMsgRateLimitItv = 5;
142 int glblIntMsgRateLimitBurst = 500;
143 char** glblDbgFiles = NULL;
144 size_t glblDbgFilesNum = 0;
145 int glblDbgWhitelist = 1;
146 int glblPermitCtlC = 0;
147 int glblInputTimeoutShutdown = 1000; /* input shutdown timeout in ms */
148 int glblShutdownQueueDoubleSize = 0;
149 static const uchar * operatingStateFile = NULL;
150 
151 uint64_t glblDevOptions = 0; /* to be used by developers only */
152 
153 pid_t glbl_ourpid;
154 #ifndef HAVE_ATOMIC_BUILTINS
155 DEF_ATOMIC_HELPER_MUT(mutTerminateInputs);
156 #endif
157 #ifdef USE_UNLIMITED_SELECT
158 static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* size of select() bitmask in bytes */
159 #endif
160 static uchar *SourceIPofLocalClient = NULL;	/* [ar] Source IP for local client to be used on multihomed host */
161 
162 tzinfo_t *tzinfos = NULL;
163 static int ntzinfos;
164 
165 /* tables for interfacing with the v6 config system */
166 static struct cnfparamdescr cnfparamdescr[] = {
167 	{ "workdirectory", eCmdHdlrString, 0 },
168 	{ "operatingstatefile", eCmdHdlrString, 0 },
169 	{ "dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0 },
170 	{ "localhostname", eCmdHdlrGetWord, 0 },
171 	{ "preservefqdn", eCmdHdlrBinary, 0 },
172 	{ "debug.onshutdown", eCmdHdlrBinary, 0 },
173 	{ "debug.logfile", eCmdHdlrString, 0 },
174 	{ "debug.gnutls", eCmdHdlrNonNegInt, 0 },
175 	{ "debug.unloadmodules", eCmdHdlrBinary, 0 },
176 	{ "defaultnetstreamdrivercafile", eCmdHdlrString, 0 },
177 	{ "defaultnetstreamdriverkeyfile", eCmdHdlrString, 0 },
178 	{ "defaultnetstreamdrivercertfile", eCmdHdlrString, 0 },
179 	{ "defaultnetstreamdriver", eCmdHdlrString, 0 },
180 	{ "maxmessagesize", eCmdHdlrSize, 0 },
181 	{ "oversizemsg.errorfile", eCmdHdlrGetWord, 0 },
182 	{ "oversizemsg.report", eCmdHdlrBinary, 0 },
183 	{ "oversizemsg.input.mode", eCmdHdlrGetWord, 0 },
184 	{ "reportchildprocessexits", eCmdHdlrGetWord, 0 },
185 	{ "action.reportsuspension", eCmdHdlrBinary, 0 },
186 	{ "action.reportsuspensioncontinuation", eCmdHdlrBinary, 0 },
187 	{ "parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0 },
188 	{ "parser.droptrailinglfonreception", eCmdHdlrBinary, 0 },
189 	{ "parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0 },
190 	{ "parser.spacelfonreceive", eCmdHdlrBinary, 0 },
191 	{ "parser.escape8bitcharactersonreceive", eCmdHdlrBinary, 0},
192 	{ "parser.escapecontrolcharactertab", eCmdHdlrBinary, 0},
193 	{ "parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0 },
194 	{ "parser.parsehostnameandtag", eCmdHdlrBinary, 0 },
195 	{ "parser.permitslashinprogramname", eCmdHdlrBinary, 0 },
196 	{ "stdlog.channelspec", eCmdHdlrString, 0 },
197 	{ "janitor.interval", eCmdHdlrPositiveInt, 0 },
198 	{ "senders.reportnew", eCmdHdlrBinary, 0 },
199 	{ "senders.reportgoneaway", eCmdHdlrBinary, 0 },
200 	{ "senders.timeoutafter", eCmdHdlrPositiveInt, 0 },
201 	{ "senders.keeptrack", eCmdHdlrBinary, 0 },
202 	{ "inputs.timeout.shutdown", eCmdHdlrPositiveInt, 0 },
203 	{ "privdrop.group.keepsupplemental", eCmdHdlrBinary, 0 },
204 	{ "privdrop.group.id", eCmdHdlrPositiveInt, 0 },
205 	{ "privdrop.group.name", eCmdHdlrGID, 0 },
206 	{ "privdrop.user.id", eCmdHdlrPositiveInt, 0 },
207 	{ "privdrop.user.name", eCmdHdlrUID, 0 },
208 	{ "net.ipprotocol", eCmdHdlrGetWord, 0 },
209 	{ "net.acladdhostnameonfail", eCmdHdlrBinary, 0 },
210 	{ "net.aclresolvehostname", eCmdHdlrBinary, 0 },
211 	{ "net.enabledns", eCmdHdlrBinary, 0 },
212 	{ "net.permitACLwarning", eCmdHdlrBinary, 0 },
213 	{ "abortonuncleanconfig", eCmdHdlrBinary, 0 },
214 	{ "variables.casesensitive", eCmdHdlrBinary, 0 },
215 	{ "environment", eCmdHdlrArray, 0 },
216 	{ "processinternalmessages", eCmdHdlrBinary, 0 },
217 	{ "umask", eCmdHdlrFileCreateMode, 0 },
218 	{ "security.abortonidresolutionfail", eCmdHdlrBinary, 0 },
219 	{ "internal.developeronly.options", eCmdHdlrInt, 0 },
220 	{ "internalmsg.ratelimit.interval", eCmdHdlrPositiveInt, 0 },
221 	{ "internalmsg.ratelimit.burst", eCmdHdlrPositiveInt, 0 },
222 	{ "internalmsg.severity", eCmdHdlrSeverity, 0 },
223 	{ "errormessagestostderr.maxnumber", eCmdHdlrPositiveInt, 0 },
224 	{ "shutdown.enable.ctlc", eCmdHdlrBinary, 0 },
225 	{ "default.action.queue.timeoutshutdown", eCmdHdlrInt, 0 },
226 	{ "default.action.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
227 	{ "default.action.queue.timeoutenqueue", eCmdHdlrInt, 0 },
228 	{ "default.action.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
229 	{ "default.ruleset.queue.timeoutshutdown", eCmdHdlrInt, 0 },
230 	{ "default.ruleset.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
231 	{ "default.ruleset.queue.timeoutenqueue", eCmdHdlrInt, 0 },
232 	{ "default.ruleset.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
233 	{ "reverselookup.cache.ttl.default", eCmdHdlrNonNegInt, 0 },
234 	{ "reverselookup.cache.ttl.enable", eCmdHdlrBinary, 0 },
235 	{ "parser.supportcompressionextension", eCmdHdlrBinary, 0 },
236 	{ "shutdown.queue.doublesize", eCmdHdlrBinary, 0 },
237 	{ "debug.files", eCmdHdlrArray, 0 },
238 	{ "debug.whitelist", eCmdHdlrBinary, 0 }
239 };
240 static struct cnfparamblk paramblk =
241 	{ CNFPARAMBLK_VERSION,
242 	  sizeof(cnfparamdescr)/sizeof(struct cnfparamdescr),
243 	  cnfparamdescr
244 	};
245 
246 static struct cnfparamdescr timezonecnfparamdescr[] = {
247 	{ "id", eCmdHdlrString, CNFPARAM_REQUIRED},
248 	{ "offset", eCmdHdlrGetWord, CNFPARAM_REQUIRED }
249 };
250 static struct cnfparamblk timezonepblk =
251 	{ CNFPARAMBLK_VERSION,
252 	  sizeof(timezonecnfparamdescr)/sizeof(struct cnfparamdescr),
253 	  timezonecnfparamdescr
254 	};
255 
256 static struct cnfparamvals *cnfparamvals = NULL;
257 /* we need to support multiple calls into our param block, so we need
258  * to persist the current settings. Note that this must be re-set
259  * each time a new config load begins (TODO: create interface?)
260  */
261 
262 int
glblGetMaxLine(void)263 glblGetMaxLine(void)
264 {
265 	return(iMaxLine);
266 }
267 
268 
269 int
GetGnuTLSLoglevel(void)270 GetGnuTLSLoglevel(void)
271 {
272 	return(iGnuTLSLoglevel);
273 }
274 
275 /* define a macro for the simple properties' set and get functions
276  * (which are always the same). This is only suitable for pretty
277  * simple cases which require neither checks nor memory allocation.
278  */
279 #define SIMP_PROP(nameFunc, nameVar, dataType) \
280 	SIMP_PROP_GET(nameFunc, nameVar, dataType) \
281 	SIMP_PROP_SET(nameFunc, nameVar, dataType)
282 #define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
283 static rsRetVal Set##nameFunc(dataType newVal) \
284 { \
285 	nameVar = newVal; \
286 	return RS_RET_OK; \
287 }
288 #define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
289 static dataType Get##nameFunc(void) \
290 { \
291 	return(nameVar); \
292 }
293 
SIMP_PROP(PreserveFQDN,bPreserveFQDN,int)294 SIMP_PROP(PreserveFQDN, bPreserveFQDN, int)
295 SIMP_PROP(mainqCnfObj, mainqCnfObj, struct cnfobj *)
296 SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int)
297 SIMP_PROP(StripDomains, StripDomains, char**)
298 SIMP_PROP(LocalHosts, LocalHosts, char**)
299 SIMP_PROP(ParserControlCharacterEscapePrefix, cCCEscapeChar, uchar)
300 SIMP_PROP(ParserDropTrailingLFOnReception, bDropTrailingLF, int)
301 SIMP_PROP(ParserEscapeControlCharactersOnReceive, bEscapeCCOnRcv, int)
302 SIMP_PROP(ParserSpaceLFOnReceive, bSpaceLFOnRcv, int)
303 SIMP_PROP(ParserEscape8BitCharactersOnReceive, bEscape8BitChars, int)
304 SIMP_PROP(ParserEscapeControlCharacterTab, bEscapeTab, int)
305 SIMP_PROP(ParserEscapeControlCharactersCStyle, bParserEscapeCCCStyle, int)
306 #ifdef USE_UNLIMITED_SELECT
307 SIMP_PROP(FdSetSize, iFdSetSize, int)
308 #endif
309 
310 SIMP_PROP_SET(DfltNetstrmDrvr, pszDfltNetstrmDrvr, uchar*) /* TODO: use custom function which frees existing value */
311 SIMP_PROP_SET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*)
312 /* TODO: use custom function which frees existing value */
313 SIMP_PROP_SET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*)
314 /* TODO: use custom function which frees existing value */
315 SIMP_PROP_SET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar*)
316 /* TODO: use custom function which frees existing value */
317 
318 #undef SIMP_PROP
319 #undef SIMP_PROP_SET
320 #undef SIMP_PROP_GET
321 
322 
323 /* return global input termination status
324  * rgerhards, 2009-07-20
325  */
326 static int GetGlobalInputTermState(void)
327 {
328 	return ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
329 }
330 
331 
332 /* set global termination state to "terminate". Note that this is a
333  * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20
334  */
SetGlobalInputTermination(void)335 static void SetGlobalInputTermination(void)
336 {
337 	ATOMIC_STORE_1_TO_INT(&bTerminateInputs, &mutTerminateInputs);
338 }
339 
340 
341 /* set the local host IP address to a specific string. Helper to
342  * small set of functions. No checks done, caller must ensure it is
343  * ok to call. Most importantly, the IP address must not already have
344  * been set. -- rgerhards, 2012-03-21
345  */
346 static rsRetVal
storeLocalHostIPIF(uchar * myIP)347 storeLocalHostIPIF(uchar *myIP)
348 {
349 	DEFiRet;
350 	if(propLocalIPIF != NULL) {
351 		CHKiRet(prop.Destruct(&propLocalIPIF));
352 	}
353 	CHKiRet(prop.Construct(&propLocalIPIF));
354 	CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP)));
355 	CHKiRet(prop.ConstructFinalize(propLocalIPIF));
356 	DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP);
357 finalize_it:
358 	RETiRet;
359 }
360 
361 
362 /* This function is used to set the IP address that is to be
363  * reported for the local host. Note that in order to ease things
364  * for the v6 config interface, we do not allow to set this more
365  * than once.
366  * rgerhards, 2012-03-21
367  */
368 static rsRetVal
setLocalHostIPIF(void * pVal,uchar * pNewVal)369 setLocalHostIPIF(void __attribute__((unused)) *pVal, uchar *pNewVal)
370 {
371 	uchar myIP[128];
372 	rsRetVal localRet;
373 	DEFiRet;
374 
375 	CHKiRet(objUse(net, CORE_COMPONENT));
376 
377 	if(propLocalIPIF_set) {
378 		LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set "
379 				"and cannot be reset; place it at TOP OF rsyslog.conf!");
380 		ABORT_FINALIZE(RS_RET_ERR);
381 	}
382 
383 	localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int) sizeof(myIP));
384 	if(localRet != RS_RET_OK) {
385 		LogError(0, RS_RET_ERR, "$LocalHostIPIF: IP address for interface "
386 				"'%s' cannnot be obtained - ignoring directive", pNewVal);
387 	} else  {
388 		storeLocalHostIPIF(myIP);
389 	}
390 
391 
392 finalize_it:
393 	free(pNewVal); /* no longer needed -> is in prop! */
394 	RETiRet;
395 }
396 
397 
398 /* This function is used to set the global work directory name.
399  * It verifies that the provided directory actually exists and
400  * emits an error message if not.
401  * rgerhards, 2011-02-16
402  */
setWorkDir(void * pVal,uchar * pNewVal)403 static rsRetVal setWorkDir(void __attribute__((unused)) *pVal, uchar *pNewVal)
404 {
405 	size_t lenDir;
406 	int i;
407 	struct stat sb;
408 	DEFiRet;
409 
410 	/* remove trailing slashes */
411 	lenDir = ustrlen(pNewVal);
412 	i = lenDir - 1;
413 	while(i > 0 && pNewVal[i] == '/') {
414 		--i;
415 	}
416 
417 	if(i < 0) {
418 		LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: empty value "
419 				"- directive ignored");
420 		ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
421 	}
422 
423 	if(i != (int) lenDir - 1) {
424 		pNewVal[i+1] = '\0';
425 		LogError(0, RS_RET_WRN_WRKDIR, "$WorkDirectory: trailing slashes "
426 			"removed, new value is '%s'", pNewVal);
427 	}
428 
429 	if(stat((char*) pNewVal, &sb) != 0) {
430 		LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s can not be "
431 				"accessed, probably does not exist - directive ignored", pNewVal);
432 		ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
433 	}
434 
435 	if(!S_ISDIR(sb.st_mode)) {
436 		LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s not a directory - directive ignored",
437 				pNewVal);
438 		ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
439 	}
440 
441 	free(pszWorkDir);
442 	pszWorkDir = pNewVal;
443 
444 finalize_it:
445 	RETiRet;
446 }
447 
448 
449 /* This function is used both by legacy and RainerScript conf. It is a real setter. */
450 static void
setMaxLine(const int64_t iNew)451 setMaxLine(const int64_t iNew)
452 {
453 	if(iNew < 128) {
454 		LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize tried to set "
455 				"to %lld, but cannot be less than 128 - set to 128 "
456 				"instead", (long long) iNew);
457 		iMaxLine = 128;
458 	} else if(iNew > (int64_t) INT_MAX) {
459 		LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize larger than "
460 				"INT_MAX (%d) - reduced to INT_MAX", INT_MAX);
461 		iMaxLine = INT_MAX;
462 	} else {
463 		iMaxLine = (int) iNew;
464 	}
465 }
466 
467 
468 
469 static rsRetVal
legacySetMaxMessageSize(void * pVal,int64_t iNew)470 legacySetMaxMessageSize(void __attribute__((unused)) *pVal, int64_t iNew)
471 {
472 	setMaxLine(iNew);
473 	return RS_RET_OK;
474 }
475 
476 static rsRetVal
setDebugFile(void * pVal,uchar * pNewVal)477 setDebugFile(void __attribute__((unused)) *pVal, uchar *pNewVal)
478 {
479 	DEFiRet;
480 	dbgSetDebugFile(pNewVal);
481 	free(pNewVal);
482 	RETiRet;
483 }
484 
485 static rsRetVal
setDebugLevel(void * pVal,int level)486 setDebugLevel(void __attribute__((unused)) *pVal, int level)
487 {
488 	DEFiRet;
489 	dbgSetDebugLevel(level);
490 	dbgprintf("debug level %d set via config file\n", level);
491 	dbgprintf("This is rsyslog version " VERSION "\n");
492 	RETiRet;
493 }
494 
ATTR_NONNULL()495 static rsRetVal ATTR_NONNULL()
496 setOversizeMsgInputMode(const uchar *const mode)
497 {
498 	DEFiRet;
499 	if(!strcmp((char*)mode, "truncate")) {
500 		oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
501 	} else if(!strcmp((char*)mode, "split")) {
502 		oversizeMsgInputMode = glblOversizeMsgInputMode_Split;
503 	} else if(!strcmp((char*)mode, "accept")) {
504 		oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
505 	} else {
506 		oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
507 	}
508 	RETiRet;
509 }
510 
ATTR_NONNULL()511 static rsRetVal ATTR_NONNULL()
512 setReportChildProcessExits(const uchar *const mode)
513 {
514 	DEFiRet;
515 	if(!strcmp((char*)mode, "none")) {
516 		reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_NONE;
517 	} else if(!strcmp((char*)mode, "errors")) {
518 		reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
519 	} else if(!strcmp((char*)mode, "all")) {
520 		reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ALL;
521 	} else {
522 		LogError(0, RS_RET_CONF_PARAM_INVLD,
523 				"invalid value '%s' for global parameter reportChildProcessExits -- ignored",
524 				mode);
525 		iRet = RS_RET_CONF_PARAM_INVLD;
526 	}
527 	RETiRet;
528 }
529 
530 static rsRetVal
setDisableDNS(int val)531 setDisableDNS(int val)
532 {
533 	bDisableDNS = val;
534 	return RS_RET_OK;
535 }
536 
537 static int
getDisableDNS(void)538 getDisableDNS(void)
539 {
540 	return bDisableDNS;
541 }
542 
543 static rsRetVal
setOption_DisallowWarning(int val)544 setOption_DisallowWarning(int val)
545 {
546 	option_DisallowWarning = val;
547 	return RS_RET_OK;
548 }
549 
550 static int
getOption_DisallowWarning(void)551 getOption_DisallowWarning(void)
552 {
553 	return option_DisallowWarning;
554 }
555 
556 static rsRetVal
setParseHOSTNAMEandTAG(int val)557 setParseHOSTNAMEandTAG(int val)
558 {
559 	bParseHOSTNAMEandTAG = val;
560 	return RS_RET_OK;
561 }
562 
563 static int
getParseHOSTNAMEandTAG(void)564 getParseHOSTNAMEandTAG(void)
565 {
566 	return bParseHOSTNAMEandTAG;
567 }
568 
569 static rsRetVal
setDefPFFamily(int level)570 setDefPFFamily(int level)
571 {
572 	DEFiRet;
573 	iDefPFFamily = level;
574 	RETiRet;
575 }
576 
577 static int
getDefPFFamily(void)578 getDefPFFamily(void)
579 {
580 	return iDefPFFamily;
581 }
582 
583 /* return our local IP.
584  * If no local IP is set, "127.0.0.1" is selected *and* set. This
585  * is an intensional side effect that we do in order to keep things
586  * consistent and avoid config errors (this will make us not accept
587  * setting the local IP address once a module has obtained it - so
588  * it forces the $LocalHostIPIF directive high up in rsyslog.conf)
589  * rgerhards, 2012-03-21
590  */
591 static prop_t*
GetLocalHostIP(void)592 GetLocalHostIP(void)
593 {
594 	assert(propLocalIPIF != NULL);
595 	return(propLocalIPIF);
596 }
597 
598 
599 /* set our local hostname. Free previous hostname, if it was already set.
600  * Note that we do now do this in a thread. As such, the method here
601  * is NOT 100% clean. If we run into issues, we need to think about
602  * refactoring the whole way we handle the local host name processing.
603  * Possibly using a PROP might be the right solution then.
604  */
605 static rsRetVal
SetLocalHostName(uchar * const newname)606 SetLocalHostName(uchar *const newname)
607 {
608 	uchar *toFree;
609 	if(LocalHostName == NULL || strcmp((const char*)LocalHostName, (const char*) newname)) {
610 		toFree = LocalHostName;
611 		LocalHostName = newname;
612 	} else {
613 		toFree = newname;
614 	}
615 	free(toFree);
616 	return RS_RET_OK;
617 }
618 
619 
620 /* return our local hostname. if it is not set, "[localhost]" is returned
621  */
622 static uchar*
GetLocalHostName(void)623 GetLocalHostName(void)
624 {
625 	uchar *pszRet;
626 
627 	if(LocalHostNameOverride != NULL) {
628 		pszRet = LocalHostNameOverride;
629 		goto done;
630 	}
631 
632 	if(LocalHostName == NULL)
633 		pszRet = (uchar*) "[localhost]";
634 	else {
635 		if(GetPreserveFQDN() == 1)
636 			pszRet = LocalFQDNName;
637 		else
638 			pszRet = LocalHostName;
639 	}
640 done:
641 	return(pszRet);
642 }
643 
644 
645 /* return the name of the file where oversize messages are written to
646  */
647 uchar*
glblGetOversizeMsgErrorFile(void)648 glblGetOversizeMsgErrorFile(void)
649 {
650 	return oversizeMsgErrorFile;
651 }
652 
653 const uchar*
glblGetOperatingStateFile(void)654 glblGetOperatingStateFile(void)
655 {
656 	return operatingStateFile;
657 }
658 
659 /* return the mode with which oversize messages will be put forward
660  */
661 int
glblGetOversizeMsgInputMode(void)662 glblGetOversizeMsgInputMode(void)
663 {
664 	return oversizeMsgInputMode;
665 }
666 
667 int
glblReportOversizeMessage(void)668 glblReportOversizeMessage(void)
669 {
670 	return reportOversizeMsg;
671 }
672 
673 
674 /* logs a message indicating that a child process has terminated.
675  * If name != NULL, prints it as the program name.
676  */
677 void
glblReportChildProcessExit(const uchar * name,pid_t pid,int status)678 glblReportChildProcessExit(const uchar *name, pid_t pid, int status)
679 {
680 	DBGPRINTF("waitpid for child %ld returned status: %2.2x\n", (long) pid, status);
681 
682 	if(reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_NONE
683 		|| (reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_ERRORS
684 			&& WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
685 		return;
686 	}
687 
688 	if(WIFEXITED(status)) {
689 		int severity = WEXITSTATUS(status) == 0 ? LOG_INFO : LOG_WARNING;
690 		if(name != NULL) {
691 			LogMsg(0, NO_ERRCODE, severity, "program '%s' (pid %ld) exited with status %d",
692 					name, (long) pid, WEXITSTATUS(status));
693 		} else {
694 			LogMsg(0, NO_ERRCODE, severity, "child process (pid %ld) exited with status %d",
695 					(long) pid, WEXITSTATUS(status));
696 		}
697 	} else if(WIFSIGNALED(status)) {
698 		if(name != NULL) {
699 			LogMsg(0, NO_ERRCODE, LOG_WARNING, "program '%s' (pid %ld) terminated by signal %d",
700 					name, (long) pid, WTERMSIG(status));
701 		} else {
702 			LogMsg(0, NO_ERRCODE, LOG_WARNING, "child process (pid %ld) terminated by signal %d",
703 					(long) pid, WTERMSIG(status));
704 		}
705 	}
706 }
707 
708 
709 /* set our local domain name. Free previous domain, if it was already set.
710  */
711 static rsRetVal
SetLocalDomain(uchar * newname)712 SetLocalDomain(uchar *newname)
713 {
714 	free(LocalDomain);
715 	LocalDomain = newname;
716 	return RS_RET_OK;
717 }
718 
719 
720 /* return our local hostname. if it is not set, "[localhost]" is returned
721  */
722 static uchar*
GetLocalDomain(void)723 GetLocalDomain(void)
724 {
725 	return LocalDomain;
726 }
727 
728 
729 /* generate the local hostname property. This must be done after the hostname info
730  * has been set as well as PreserveFQDN.
731  * rgerhards, 2009-06-30
732  * NOTE: This function tries to avoid locking by not destructing the previous value
733  * immediately. This is so that current readers can  continue to use the previous name.
734  * Otherwise, we would need to use read/write locks to protect the update process.
735  * In order to do so, we save the previous value and delete it when we are called again
736  * the next time. Note that this in theory is racy and can lead to a double-free.
737  * In practice, however, the window of exposure to trigger this is extremely short
738  * and as this functions is very infrequently being called (on HUP), the trigger
739  * condition for this bug is so highly unlikely that it never occurs in practice.
740  * Probably if you HUP rsyslog every few milliseconds, but who does that...
741  * To further reduce risk potential, we do only update the property when there
742  * actually is a hostname change, which makes it even less likely.
743  * rgerhards, 2013-10-28
744  */
745 static rsRetVal
GenerateLocalHostNameProperty(void)746 GenerateLocalHostNameProperty(void)
747 {
748 	uchar *pszPrev;
749 	int lenPrev;
750 	prop_t *hostnameNew;
751 	uchar *pszName;
752 	DEFiRet;
753 
754 	if(propLocalHostNameToDelete != NULL)
755 		prop.Destruct(&propLocalHostNameToDelete);
756 
757 	if(LocalHostNameOverride == NULL) {
758 		if(LocalHostName == NULL)
759 			pszName = (uchar*) "[localhost]";
760 		else {
761 			if(GetPreserveFQDN() == 1)
762 				pszName = LocalFQDNName;
763 			else
764 				pszName = LocalHostName;
765 		}
766 	} else { /* local hostname is overriden via config */
767 		pszName = LocalHostNameOverride;
768 	}
769 	DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName);
770 
771 	if(propLocalHostName == NULL)
772 		pszPrev = (uchar*)""; /* make sure strcmp() below does not match */
773 	else
774 		prop.GetString(propLocalHostName, &pszPrev, &lenPrev);
775 
776 	if(ustrcmp(pszPrev, pszName)) {
777 		/* we need to update */
778 		CHKiRet(prop.Construct(&hostnameNew));
779 		CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName)));
780 		CHKiRet(prop.ConstructFinalize(hostnameNew));
781 		propLocalHostNameToDelete = propLocalHostName;
782 		propLocalHostName = hostnameNew;
783 	}
784 
785 finalize_it:
786 	RETiRet;
787 }
788 
789 
790 /* return our local hostname as a string property
791  */
792 static prop_t*
GetLocalHostNameProp(void)793 GetLocalHostNameProp(void)
794 {
795 	return(propLocalHostName);
796 }
797 
798 
799 static rsRetVal
SetLocalFQDNName(uchar * newname)800 SetLocalFQDNName(uchar *newname)
801 {
802 	free(LocalFQDNName);
803 	LocalFQDNName = newname;
804 	return RS_RET_OK;
805 }
806 
807 /* return the current localhost name as FQDN (requires FQDN to be set)
808  * TODO: we should set the FQDN ourselfs in here!
809  */
810 static uchar*
GetLocalFQDNName(void)811 GetLocalFQDNName(void)
812 {
813 	return(LocalFQDNName == NULL ? (uchar*) "[localhost]" : LocalFQDNName);
814 }
815 
816 
817 /* return the current working directory */
818 static uchar*
GetWorkDir(void)819 GetWorkDir(void)
820 {
821 	return(pszWorkDir == NULL ? (uchar*) "" : pszWorkDir);
822 }
823 
824 /* return the "raw" working directory, which means
825  * NULL if unset.
826  */
827 const uchar *
glblGetWorkDirRaw(void)828 glblGetWorkDirRaw(void)
829 {
830 	return pszWorkDir;
831 }
832 
833 /* return the current default netstream driver */
834 static uchar*
GetDfltNetstrmDrvr(void)835 GetDfltNetstrmDrvr(void)
836 {
837 	return(pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : pszDfltNetstrmDrvr);
838 }
839 
840 
841 /* return the current default netstream driver CA File */
842 static uchar*
GetDfltNetstrmDrvrCAF(void)843 GetDfltNetstrmDrvrCAF(void)
844 {
845 	return(pszDfltNetstrmDrvrCAF);
846 }
847 
848 
849 /* return the current default netstream driver key File */
850 static uchar*
GetDfltNetstrmDrvrKeyFile(void)851 GetDfltNetstrmDrvrKeyFile(void)
852 {
853 	return(pszDfltNetstrmDrvrKeyFile);
854 }
855 
856 
857 /* return the current default netstream driver certificate File */
858 static uchar*
GetDfltNetstrmDrvrCertFile(void)859 GetDfltNetstrmDrvrCertFile(void)
860 {
861 	return(pszDfltNetstrmDrvrCertFile);
862 }
863 
864 
865 /* [ar] Source IP for local client to be used on multihomed host */
866 static rsRetVal
SetSourceIPofLocalClient(uchar * newname)867 SetSourceIPofLocalClient(uchar *newname)
868 {
869 	if(SourceIPofLocalClient != NULL) {
870 		free(SourceIPofLocalClient); }
871 	SourceIPofLocalClient = newname;
872 	return RS_RET_OK;
873 }
874 
875 static uchar*
GetSourceIPofLocalClient(void)876 GetSourceIPofLocalClient(void)
877 {
878 	return(SourceIPofLocalClient);
879 }
880 
881 
882 /* queryInterface function
883  * rgerhards, 2008-02-21
884  */
885 BEGINobjQueryInterface(glbl)
886 CODESTARTobjQueryInterface(glbl)
887 	if(pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */
888 		ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
889 	}
890 
891 	/* ok, we have the right interface, so let's fill it
892 	 * Please note that we may also do some backwards-compatibility
893 	 * work here (if we can support an older interface version - that,
894 	 * of course, also affects the "if" above).
895 	 */
896 	pIf->GetWorkDir = GetWorkDir;
897 	pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty;
898 	pIf->GetLocalHostNameProp = GetLocalHostNameProp;
899 	pIf->GetLocalHostIP = GetLocalHostIP;
900 	pIf->SetGlobalInputTermination = SetGlobalInputTermination;
901 	pIf->GetGlobalInputTermState = GetGlobalInputTermState;
902 	pIf->GetSourceIPofLocalClient = GetSourceIPofLocalClient;	/* [ar] */
903 	pIf->SetSourceIPofLocalClient = SetSourceIPofLocalClient;	/* [ar] */
904 	pIf->SetDefPFFamily = setDefPFFamily;
905 	pIf->GetDefPFFamily = getDefPFFamily;
906 	pIf->SetDisableDNS = setDisableDNS;
907 	pIf->GetDisableDNS = getDisableDNS;
908 	pIf->GetMaxLine = glblGetMaxLine;
909 	pIf->SetOption_DisallowWarning = setOption_DisallowWarning;
910 	pIf->GetOption_DisallowWarning = getOption_DisallowWarning;
911 	pIf->SetParseHOSTNAMEandTAG = setParseHOSTNAMEandTAG;
912 	pIf->GetParseHOSTNAMEandTAG = getParseHOSTNAMEandTAG;
913 #define SIMP_PROP(name) \
914 	pIf->Get##name = Get##name; \
915 	pIf->Set##name = Set##name;
916 	SIMP_PROP(PreserveFQDN);
917 	SIMP_PROP(DropMalPTRMsgs);
918 	SIMP_PROP(mainqCnfObj);
919 	SIMP_PROP(LocalFQDNName)
SIMP_PROP(LocalHostName)920 	SIMP_PROP(LocalHostName)
921 	SIMP_PROP(LocalDomain)
922 	SIMP_PROP(StripDomains)
923 	SIMP_PROP(LocalHosts)
924 	SIMP_PROP(ParserControlCharacterEscapePrefix)
925 	SIMP_PROP(ParserDropTrailingLFOnReception)
926 	SIMP_PROP(ParserEscapeControlCharactersOnReceive)
927 	SIMP_PROP(ParserSpaceLFOnReceive)
928 	SIMP_PROP(ParserEscape8BitCharactersOnReceive)
929 	SIMP_PROP(ParserEscapeControlCharacterTab)
930 	SIMP_PROP(ParserEscapeControlCharactersCStyle)
931 	SIMP_PROP(DfltNetstrmDrvr)
932 	SIMP_PROP(DfltNetstrmDrvrCAF)
933 	SIMP_PROP(DfltNetstrmDrvrKeyFile)
934 	SIMP_PROP(DfltNetstrmDrvrCertFile)
935 #ifdef USE_UNLIMITED_SELECT
936 	SIMP_PROP(FdSetSize)
937 #endif
938 #undef	SIMP_PROP
939 finalize_it:
940 ENDobjQueryInterface(glbl)
941 
942 /* Reset config variables to default values.
943  * rgerhards, 2008-04-17
944  */
945 static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
946 {
947 	free(pszDfltNetstrmDrvr);
948 	pszDfltNetstrmDrvr = NULL;
949 	free(pszDfltNetstrmDrvrCAF);
950 	pszDfltNetstrmDrvrCAF = NULL;
951 	free(pszDfltNetstrmDrvrKeyFile);
952 	pszDfltNetstrmDrvrKeyFile = NULL;
953 	free(pszDfltNetstrmDrvrCertFile);
954 	pszDfltNetstrmDrvrCertFile = NULL;
955 	free(LocalHostNameOverride);
956 	LocalHostNameOverride = NULL;
957 	free(oversizeMsgErrorFile);
958 	oversizeMsgErrorFile = NULL;
959 	oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
960 	reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
961 	free(pszWorkDir);
962 	pszWorkDir = NULL;
963 	free((void*)operatingStateFile);
964 	operatingStateFile = NULL;
965 	bDropMalPTRMsgs = 0;
966 	bPreserveFQDN = 0;
967 	iMaxLine = 8192;
968 	cCCEscapeChar = '#';
969 	bDropTrailingLF = 1;
970 	reportOversizeMsg = 1;
971 	bEscapeCCOnRcv = 1; /* default is to escape control characters */
972 	bSpaceLFOnRcv = 0;
973 	bEscape8BitChars = 0; /* default is not to escape control characters */
974 	bEscapeTab = 1; /* default is to escape tab characters */
975 	bParserEscapeCCCStyle = 0;
976 #ifdef USE_UNLIMITED_SELECT
977 	iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask);
978 #endif
979 	return RS_RET_OK;
980 }
981 
982 
983 /* Prepare for new config
984  */
985 void
glblPrepCnf(void)986 glblPrepCnf(void)
987 {
988 	free(mainqCnfObj);
989 	mainqCnfObj = NULL;
990 	free(cnfparamvals);
991 	cnfparamvals = NULL;
992 }
993 
994 
995 static void
freeTimezoneInfo(void)996 freeTimezoneInfo(void)
997 {
998 	int i;
999 	for(i = 0 ; i < ntzinfos ; ++i)
1000 		free(tzinfos[i].id);
1001 	free(tzinfos);
1002 	tzinfos = NULL;
1003 }
1004 
1005 static void
displayTzinfos(void)1006 displayTzinfos(void)
1007 {
1008 	int i;
1009 	if(!Debug)
1010 		return;
1011 	for(i = 0 ; i < ntzinfos ; ++i)
1012 		dbgprintf("tzinfo: '%s':%c%2.2d:%2.2d\n",
1013 			tzinfos[i].id, tzinfos[i].offsMode,
1014 			tzinfos[i].offsHour, tzinfos[i].offsMin);
1015 }
1016 
1017 
1018 /* Note: this function is NOT thread-safe!
1019  * This is currently not needed as used only during
1020  * initialization.
1021  */
1022 static rsRetVal
addTimezoneInfo(uchar * tzid,char offsMode,int8_t offsHour,int8_t offsMin)1023 addTimezoneInfo(uchar *tzid, char offsMode, int8_t offsHour, int8_t offsMin)
1024 {
1025 	DEFiRet;
1026 	tzinfo_t *newti;
1027 	CHKmalloc(newti = realloc(tzinfos, (ntzinfos+1)*sizeof(tzinfo_t)));
1028 	if((newti[ntzinfos].id = strdup((char*)tzid)) == NULL) {
1029 		free(newti);
1030 		DBGPRINTF("addTimezoneInfo: strdup failed with OOM\n");
1031 		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
1032 	}
1033 	newti[ntzinfos].offsMode = offsMode;
1034 	newti[ntzinfos].offsHour = offsHour;
1035 	newti[ntzinfos].offsMin = offsMin;
1036 	++ntzinfos, tzinfos = newti;
1037 finalize_it:
1038 	RETiRet;
1039 }
1040 
1041 
1042 static int
bs_arrcmp_tzinfo(const void * s1,const void * s2)1043 bs_arrcmp_tzinfo(const void *s1, const void *s2)
1044 {
1045 	return strcmp((char*)s1, (char*)((tzinfo_t*)s2)->id);
1046 }
1047 /* returns matching timezone info or NULL if no entry exists */
1048 tzinfo_t*
glblFindTimezoneInfo(char * id)1049 glblFindTimezoneInfo(char *id)
1050 {
1051 	return (tzinfo_t*) bsearch(id, tzinfos, ntzinfos, sizeof(tzinfo_t), bs_arrcmp_tzinfo);
1052 }
1053 
1054 /* handle the timezone() object. Each incarnation adds one additional
1055  * zone info to the global table of time zones.
1056  */
1057 
1058 int
bs_arrcmp_glblDbgFiles(const void * s1,const void * s2)1059 bs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
1060 {
1061 	return strcmp((char*)s1, *(char**)s2);
1062 }
1063 
1064 void
glblProcessTimezone(struct cnfobj * o)1065 glblProcessTimezone(struct cnfobj *o)
1066 {
1067 	struct cnfparamvals *pvals;
1068 	uchar *id = NULL;
1069 	uchar *offset = NULL;
1070 	char offsMode;
1071 	int8_t offsHour;
1072 	int8_t offsMin;
1073 	int i;
1074 
1075 	pvals = nvlstGetParams(o->nvlst, &timezonepblk, NULL);
1076 	if(pvals == NULL) {
1077 		LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing timezone "
1078 				"config parameters");
1079 		goto done;
1080 	}
1081 	if(Debug) {
1082 		dbgprintf("timezone param blk after glblProcessTimezone:\n");
1083 		cnfparamsPrint(&timezonepblk, pvals);
1084 	}
1085 
1086 	for(i = 0 ; i < timezonepblk.nParams ; ++i) {
1087 		if(!pvals[i].bUsed)
1088 			continue;
1089 		if(!strcmp(timezonepblk.descr[i].name, "id")) {
1090 			id = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
1091 		} else if(!strcmp(timezonepblk.descr[i].name, "offset")) {
1092 			offset = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
1093 		} else {
1094 			dbgprintf("glblProcessTimezone: program error, non-handled "
1095 			  "param '%s'\n", timezonepblk.descr[i].name);
1096 		}
1097 	}
1098 
1099 	/* note: the following two checks for NULL are not strictly necessary
1100 	 * as these are required parameters for the config block. But we keep
1101 	 * them to make the clang static analyzer happy, which also helps
1102 	 * guard against logic errors.
1103 	 */
1104 	if(offset == NULL) {
1105 		parser_errmsg("offset parameter missing (logic error?), timezone config ignored");
1106 		goto done;
1107 	}
1108 	if(id == NULL) {
1109 		parser_errmsg("id parameter missing (logic error?), timezone config ignored");
1110 		goto done;
1111 	}
1112 
1113 	if(   strlen((char*)offset) != 6
1114 	   || !(offset[0] == '-' || offset[0] == '+')
1115 	   || !(isdigit(offset[1]) && isdigit(offset[2]))
1116 	   || offset[3] != ':'
1117 	   || !(isdigit(offset[4]) && isdigit(offset[5]))
1118 	  ) {
1119 		parser_errmsg("timezone offset has invalid format. Must be +/-hh:mm, e.g. \"-07:00\".");
1120 		goto done;
1121 	}
1122 
1123 	offsHour = (offset[1] - '0') * 10 + offset[2] - '0';
1124 	offsMin  = (offset[4] - '0') * 10 + offset[5] - '0';
1125 	offsMode = offset[0];
1126 
1127 	if(offsHour > 12 || offsMin > 59) {
1128 		parser_errmsg("timezone offset outside of supported range (hours 0..12, minutes 0..59)");
1129 		goto done;
1130 	}
1131 
1132 	addTimezoneInfo(id, offsMode, offsHour, offsMin);
1133 
1134 done:
1135 	cnfparamvalsDestruct(pvals, &timezonepblk);
1136 	free(id);
1137 	free(offset);
1138 }
1139 
1140 /* handle a global config object. Note that multiple global config statements
1141  * are permitted (because of plugin support), so once we got a param block,
1142  * we need to hold to it.
1143  * rgerhards, 2011-07-19
1144  */
1145 void
glblProcessCnf(struct cnfobj * o)1146 glblProcessCnf(struct cnfobj *o)
1147 {
1148 	int i;
1149 
1150 	cnfparamvals = nvlstGetParams(o->nvlst, &paramblk, cnfparamvals);
1151 	if(cnfparamvals == NULL) {
1152 		LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing global "
1153 				"config parameters [global(...)]");
1154 		goto done;
1155 	}
1156 	if(Debug) {
1157 		dbgprintf("glbl param blk after glblProcessCnf:\n");
1158 		cnfparamsPrint(&paramblk, cnfparamvals);
1159 	}
1160 
1161 	/* The next thing is a bit hackish and should be changed in higher
1162 	 * versions. There are a select few parameters which we need to
1163 	 * act on immediately. These are processed here.
1164 	 */
1165 	for(i = 0 ; i < paramblk.nParams ; ++i) {
1166 		if(!cnfparamvals[i].bUsed)
1167 			continue;
1168 		if(!strcmp(paramblk.descr[i].name, "processinternalmessages")) {
1169 			bProcessInternalMessages = (int) cnfparamvals[i].val.d.n;
1170 			cnfparamvals[i].bUsed = TRUE;
1171 		} else if(!strcmp(paramblk.descr[i].name, "internal.developeronly.options")) {
1172 			glblDevOptions = (uint64_t) cnfparamvals[i].val.d.n;
1173 			cnfparamvals[i].bUsed = TRUE;
1174 		} else if(!strcmp(paramblk.descr[i].name, "stdlog.channelspec")) {
1175 #ifndef ENABLE_LIBLOGGING_STDLOG
1176 			LogError(0, RS_RET_ERR, "rsyslog wasn't "
1177 				"compiled with liblogging-stdlog support. "
1178 				"The 'stdlog.channelspec' parameter "
1179 				"is ignored. Note: the syslog API is used instead.\n");
1180 #else
1181 			stdlog_chanspec = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1182 			/* we need to re-open with the new channel */
1183 			stdlog_close(stdlog_hdl);
1184 			stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG,
1185 					(char*) stdlog_chanspec);
1186 			cnfparamvals[i].bUsed = TRUE;
1187 #endif
1188 		} else if(!strcmp(paramblk.descr[i].name, "operatingstatefile")) {
1189 			if(operatingStateFile != NULL) {
1190 				LogError(errno, RS_RET_PARAM_ERROR,
1191 					"error: operatingStateFile already set to '%s' - "
1192 					"new value ignored", operatingStateFile);
1193 			} else {
1194 				operatingStateFile = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1195 				osf_open();
1196 			}
1197 		} else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
1198 			loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
1199 			cnfparamvals[i].bUsed = TRUE;
1200 		}
1201 	}
1202 done:	return;
1203 }
1204 
1205 /* Set mainq parameters. Note that when this is not called, we'll use the
1206  * legacy parameter config. mainq parameters can only be set once.
1207  */
1208 void
glblProcessMainQCnf(struct cnfobj * o)1209 glblProcessMainQCnf(struct cnfobj *o)
1210 {
1211 	if(mainqCnfObj == NULL) {
1212 		mainqCnfObj = o;
1213 	} else {
1214 		LogError(0, RS_RET_ERR, "main_queue() object can only be specified "
1215 				"once - all but first ignored\n");
1216 	}
1217 }
1218 
1219 /* destruct the main q cnf object after it is no longer needed. This is
1220  * also used to do some final checks.
1221  */
1222 void
glblDestructMainqCnfObj(void)1223 glblDestructMainqCnfObj(void)
1224 {
1225 	/* Only destruct if not NULL! */
1226 	if (mainqCnfObj != NULL) {
1227 		nvlstChkUnused(mainqCnfObj->nvlst);
1228 		cnfobjDestruct(mainqCnfObj);
1229 		mainqCnfObj = NULL;
1230 	}
1231 }
1232 
1233 /* comparison function for qsort() and string array compare
1234  * this is for the string lookup table type
1235  */
1236 static int
qs_arrcmp_tzinfo(const void * s1,const void * s2)1237 qs_arrcmp_tzinfo(const void *s1, const void *s2)
1238 {
1239 	return strcmp(((tzinfo_t*)s1)->id, ((tzinfo_t*)s2)->id);
1240 }
1241 
1242 static int
qs_arrcmp_glblDbgFiles(const void * s1,const void * s2)1243 qs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
1244 {
1245 	return strcmp(*((char**)s1), *((char**)s2));
1246 }
1247 
1248 /* set an environment variable */
1249 static rsRetVal
do_setenv(const char * const var)1250 do_setenv(const char *const var)
1251 {
1252 	char varname[128];
1253 	const char *val = var;
1254 	size_t i;
1255 	DEFiRet;
1256 
1257 	for(i = 0 ; *val != '=' ; ++i, ++val) {
1258 		if(i == sizeof(varname)-i) {
1259 			parser_errmsg("environment variable name too long "
1260 				"[max %zu chars] or malformed entry: '%s'",
1261 				sizeof(varname)-1, var);
1262 			ABORT_FINALIZE(RS_RET_ERR_SETENV);
1263 		}
1264 		if(*val == '\0') {
1265 			parser_errmsg("environment variable entry is missing "
1266 				"equal sign (for value): '%s'", var);
1267 			ABORT_FINALIZE(RS_RET_ERR_SETENV);
1268 		}
1269 		varname[i] = *val;
1270 	}
1271 	varname[i] = '\0';
1272 	++val;
1273 	DBGPRINTF("do_setenv, var '%s', val '%s'\n", varname, val);
1274 
1275 	if(setenv(varname, val, 1) != 0) {
1276 		char errStr[1024];
1277 		rs_strerror_r(errno, errStr, sizeof(errStr));
1278 		parser_errmsg("error setting environment variable "
1279 			"'%s' to '%s': %s", varname, val, errStr);
1280 		ABORT_FINALIZE(RS_RET_ERR_SETENV);
1281 	}
1282 
1283 
1284 finalize_it:
1285 	RETiRet;
1286 }
1287 
1288 
1289 /* This processes the "regular" parameters which are to be set after the
1290  * config has been fully loaded.
1291  */
1292 rsRetVal
glblDoneLoadCnf(void)1293 glblDoneLoadCnf(void)
1294 {
1295 	int i;
1296 	unsigned char *cstr;
1297 	FILE *fp;
1298 	DEFiRet;
1299 	CHKiRet(objUse(net, CORE_COMPONENT));
1300 
1301 	if(ntzinfos > 0) {
1302 		qsort(tzinfos, ntzinfos, sizeof(tzinfo_t), qs_arrcmp_tzinfo);
1303 	}
1304 	DBGPRINTF("Timezone information table (%d entries):\n", ntzinfos);
1305 	displayTzinfos();
1306 
1307 	if(cnfparamvals == NULL)
1308 		goto finalize_it;
1309 
1310 	for(i = 0 ; i < paramblk.nParams ; ++i) {
1311 		if(!cnfparamvals[i].bUsed)
1312 			continue;
1313 		if(!strcmp(paramblk.descr[i].name, "workdirectory")) {
1314 			cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1315 			setWorkDir(NULL, cstr);
1316 		} else if(!strcmp(paramblk.descr[i].name, "variables.casesensitive")) {
1317 			const int val = (int) cnfparamvals[i].val.d.n;
1318 			fjson_global_do_case_sensitive_comparison(val);
1319 			DBGPRINTF("global/config: set case sensitive variables to %d\n",
1320 				val);
1321 		} else if(!strcmp(paramblk.descr[i].name, "localhostname")) {
1322 			free(LocalHostNameOverride);
1323 			LocalHostNameOverride = (uchar*)
1324 				es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1325 		} else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriverkeyfile")) {
1326 			free(pszDfltNetstrmDrvrKeyFile);
1327 			uchar *const fn = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1328 			fp = fopen((const char*)fn, "r");
1329 			if(fp == NULL) {
1330 				LogError(errno, RS_RET_NO_FILE_ACCESS,
1331 					"error: defaultnetstreamdriverkeyfile '%s' "
1332 					"could not be accessed", fn);
1333 			} else {
1334 				fclose(fp);
1335 				pszDfltNetstrmDrvrKeyFile = fn;
1336 			}
1337 		} else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercertfile")) {
1338 			free(pszDfltNetstrmDrvrCertFile);
1339 			uchar *const fn = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1340 			fp = fopen((const char*)fn, "r");
1341 			if(fp == NULL) {
1342 				LogError(errno, RS_RET_NO_FILE_ACCESS,
1343 					"error: defaultnetstreamdrivercertfile '%s' "
1344 					"could not be accessed", fn);
1345 			} else {
1346 				fclose(fp);
1347 				pszDfltNetstrmDrvrCertFile = fn;
1348 			}
1349 		} else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercafile")) {
1350 			free(pszDfltNetstrmDrvrCAF);
1351 			uchar *const fn = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1352 			fp = fopen((const char*)fn, "r");
1353 			if(fp == NULL) {
1354 				LogError(errno, RS_RET_NO_FILE_ACCESS,
1355 					"error: defaultnetstreamdrivercafile file '%s' "
1356 					"could not be accessed", fn);
1357 			} else {
1358 				fclose(fp);
1359 				pszDfltNetstrmDrvrCAF = fn;
1360 			}
1361 		} else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriver")) {
1362 			free(pszDfltNetstrmDrvr);
1363 			pszDfltNetstrmDrvr = (uchar*)
1364 				es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1365 		} else if(!strcmp(paramblk.descr[i].name, "preservefqdn")) {
1366 			bPreserveFQDN = (int) cnfparamvals[i].val.d.n;
1367 		} else if(!strcmp(paramblk.descr[i].name,
1368 				"dropmsgswithmaliciousdnsptrrecords")) {
1369 			bDropMalPTRMsgs = (int) cnfparamvals[i].val.d.n;
1370 		} else if(!strcmp(paramblk.descr[i].name, "action.reportsuspension")) {
1371 			bActionReportSuspension = (int) cnfparamvals[i].val.d.n;
1372 		} else if(!strcmp(paramblk.descr[i].name, "action.reportsuspensioncontinuation")) {
1373 			bActionReportSuspensionCont = (int) cnfparamvals[i].val.d.n;
1374 		} else if(!strcmp(paramblk.descr[i].name, "maxmessagesize")) {
1375 			setMaxLine(cnfparamvals[i].val.d.n);
1376 		} else if(!strcmp(paramblk.descr[i].name, "oversizemsg.errorfile")) {
1377 			free(oversizeMsgErrorFile);
1378 			oversizeMsgErrorFile = (uchar*)es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1379 		} else if(!strcmp(paramblk.descr[i].name, "oversizemsg.report")) {
1380 			reportOversizeMsg = (int) cnfparamvals[i].val.d.n;
1381 		} else if(!strcmp(paramblk.descr[i].name, "oversizemsg.input.mode")) {
1382 			const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1383 			setOversizeMsgInputMode((uchar*) tmp);
1384 			free((void*)tmp);
1385 		} else if(!strcmp(paramblk.descr[i].name, "reportchildprocessexits")) {
1386 			const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1387 			setReportChildProcessExits((uchar*) tmp);
1388 			free((void*)tmp);
1389 		} else if(!strcmp(paramblk.descr[i].name, "debug.onshutdown")) {
1390 			glblDebugOnShutdown = (int) cnfparamvals[i].val.d.n;
1391 			LogError(0, RS_RET_OK, "debug: onShutdown set to %d", glblDebugOnShutdown);
1392 		} else if(!strcmp(paramblk.descr[i].name, "debug.gnutls")) {
1393 			iGnuTLSLoglevel = (int) cnfparamvals[i].val.d.n;
1394 		} else if(!strcmp(paramblk.descr[i].name, "debug.unloadmodules")) {
1395 			glblUnloadModules = (int) cnfparamvals[i].val.d.n;
1396 		} else if(!strcmp(paramblk.descr[i].name, "parser.controlcharacterescapeprefix")) {
1397 			uchar* tmp = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1398 			cCCEscapeChar = tmp[0];
1399 			free(tmp);
1400 		} else if(!strcmp(paramblk.descr[i].name, "parser.droptrailinglfonreception")) {
1401 			bDropTrailingLF = (int) cnfparamvals[i].val.d.n;
1402 		} else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) {
1403 			bEscapeCCOnRcv = (int) cnfparamvals[i].val.d.n;
1404 		} else if(!strcmp(paramblk.descr[i].name, "parser.spacelfonreceive")) {
1405 			bSpaceLFOnRcv = (int) cnfparamvals[i].val.d.n;
1406 		} else if(!strcmp(paramblk.descr[i].name, "parser.escape8bitcharactersonreceive")) {
1407 			bEscape8BitChars = (int) cnfparamvals[i].val.d.n;
1408 		} else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactertab")) {
1409 			bEscapeTab = (int) cnfparamvals[i].val.d.n;
1410 		} else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) {
1411 			bParserEscapeCCCStyle = (int) cnfparamvals[i].val.d.n;
1412 		} else if(!strcmp(paramblk.descr[i].name, "parser.parsehostnameandtag")) {
1413 			bParseHOSTNAMEandTAG = (int) cnfparamvals[i].val.d.n;
1414 		} else if(!strcmp(paramblk.descr[i].name, "parser.permitslashinprogramname")) {
1415 			bPermitSlashInProgramname = (int) cnfparamvals[i].val.d.n;
1416 		} else if(!strcmp(paramblk.descr[i].name, "debug.logfile")) {
1417 			if(pszAltDbgFileName == NULL) {
1418 				pszAltDbgFileName = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1419 				/* can actually happen if debug system also opened altdbg */
1420 				if(altdbg != -1) {
1421 					close(altdbg);
1422 				}
1423 				if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY
1424 				|O_CLOEXEC, S_IRUSR|S_IWUSR)) == -1) {
1425 					LogError(0, RS_RET_ERR, "debug log file '%s' could not be opened",
1426 							pszAltDbgFileName);
1427 				}
1428 			}
1429 			LogError(0, RS_RET_OK, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg);
1430 		} else if(!strcmp(paramblk.descr[i].name, "janitor.interval")) {
1431 			janitorInterval = (int) cnfparamvals[i].val.d.n;
1432 		} else if(!strcmp(paramblk.descr[i].name, "net.ipprotocol")) {
1433 			char *proto = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
1434 			if(!strcmp(proto, "unspecified")) {
1435 				iDefPFFamily = PF_UNSPEC;
1436 			} else if(!strcmp(proto, "ipv4-only")) {
1437 				iDefPFFamily = PF_INET;
1438 			} else if(!strcmp(proto, "ipv6-only")) {
1439 				iDefPFFamily = PF_INET6;
1440 			} else{
1441 				LogError(0, RS_RET_ERR, "invalid net.ipprotocol "
1442 					"parameter '%s' -- ignored", proto);
1443 			}
1444 			free(proto);
1445 		} else if(!strcmp(paramblk.descr[i].name, "senders.reportnew")) {
1446 			glblReportNewSenders = (int) cnfparamvals[i].val.d.n;
1447 		} else if(!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) {
1448 			glblReportGoneAwaySenders = (int) cnfparamvals[i].val.d.n;
1449 		} else if(!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) {
1450 			glblSenderStatsTimeout = (int) cnfparamvals[i].val.d.n;
1451 		} else if(!strcmp(paramblk.descr[i].name, "senders.keeptrack")) {
1452 			glblSenderKeepTrack = (int) cnfparamvals[i].val.d.n;
1453 		} else if(!strcmp(paramblk.descr[i].name, "inputs.timeout.shutdown")) {
1454 			glblInputTimeoutShutdown = (int) cnfparamvals[i].val.d.n;
1455 		} else if(!strcmp(paramblk.descr[i].name, "privdrop.group.keepsupplemental")) {
1456 			loadConf->globals.gidDropPrivKeepSupplemental = (int) cnfparamvals[i].val.d.n;
1457 		} else if(!strcmp(paramblk.descr[i].name, "privdrop.group.id")) {
1458 			loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
1459 		} else if(!strcmp(paramblk.descr[i].name, "privdrop.group.name")) {
1460 			loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
1461 		} else if(!strcmp(paramblk.descr[i].name, "privdrop.user.id")) {
1462 			loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
1463 		} else if(!strcmp(paramblk.descr[i].name, "privdrop.user.name")) {
1464 			loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
1465 		} else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
1466 			loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
1467 		} else if(!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) {
1468 			*(net.pACLAddHostnameOnFail) = (int) cnfparamvals[i].val.d.n;
1469 		} else if(!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) {
1470 			*(net.pACLDontResolve) = !((int) cnfparamvals[i].val.d.n);
1471 		} else if(!strcmp(paramblk.descr[i].name, "net.enabledns")) {
1472 			setDisableDNS(!((int) cnfparamvals[i].val.d.n));
1473 		} else if(!strcmp(paramblk.descr[i].name, "net.permitwarning")) {
1474 			setOption_DisallowWarning(!((int) cnfparamvals[i].val.d.n));
1475 		} else if(!strcmp(paramblk.descr[i].name, "abortonuncleanconfig")) {
1476 			loadConf->globals.bAbortOnUncleanConfig = cnfparamvals[i].val.d.n;
1477 		} else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.burst")) {
1478 			glblIntMsgRateLimitBurst = (int) cnfparamvals[i].val.d.n;
1479 		} else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.interval")) {
1480 			glblIntMsgRateLimitItv = (int) cnfparamvals[i].val.d.n;
1481 		} else if(!strcmp(paramblk.descr[i].name, "internalmsg.severity")) {
1482 			glblIntMsgsSeverityFilter = (int) cnfparamvals[i].val.d.n;
1483 			if((glblIntMsgsSeverityFilter < 0) || (glblIntMsgsSeverityFilter > 7)) {
1484 				parser_errmsg("invalid internalmsg.severity value");
1485 				glblIntMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER;
1486 			}
1487 		} else if(!strcmp(paramblk.descr[i].name, "environment")) {
1488 			for(int j = 0 ; j <  cnfparamvals[i].val.d.ar->nmemb ; ++j) {
1489 				char *const var = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
1490 				do_setenv(var);
1491 				free(var);
1492 			}
1493 		} else if(!strcmp(paramblk.descr[i].name, "errormessagestostderr.maxnumber")) {
1494 			loadConf->globals.maxErrMsgToStderr = (int) cnfparamvals[i].val.d.n;
1495 		} else if(!strcmp(paramblk.descr[i].name, "debug.files")) {
1496 			free(glblDbgFiles); /* "fix" Coverity false positive */
1497 			glblDbgFilesNum = cnfparamvals[i].val.d.ar->nmemb;
1498 			glblDbgFiles = (char**) malloc(cnfparamvals[i].val.d.ar->nmemb * sizeof(char*));
1499 			for(int j = 0 ; j <  cnfparamvals[i].val.d.ar->nmemb ; ++j) {
1500 				glblDbgFiles[j] = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
1501 			}
1502 			qsort(glblDbgFiles, glblDbgFilesNum, sizeof(char*), qs_arrcmp_glblDbgFiles);
1503 		} else if(!strcmp(paramblk.descr[i].name, "debug.whitelist")) {
1504 			glblDbgWhitelist = (int) cnfparamvals[i].val.d.n;
1505 		} else if(!strcmp(paramblk.descr[i].name, "shutdown.queue.doublesize")) {
1506 			glblShutdownQueueDoubleSize = (int) cnfparamvals[i].val.d.n;
1507 		} else if(!strcmp(paramblk.descr[i].name, "umask")) {
1508 			loadConf->globals.umask = (int) cnfparamvals[i].val.d.n;
1509 		} else if(!strcmp(paramblk.descr[i].name, "shutdown.enable.ctlc")) {
1510 			glblPermitCtlC = (int) cnfparamvals[i].val.d.n;
1511 		} else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutshutdown")) {
1512 			actq_dflt_toQShutdown = cnfparamvals[i].val.d.n;
1513 		} else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutactioncompletion")) {
1514 			actq_dflt_toActShutdown = cnfparamvals[i].val.d.n;
1515 		} else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutenqueue")) {
1516 			actq_dflt_toEnq = cnfparamvals[i].val.d.n;
1517 		} else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutworkerthreadshutdown")) {
1518 			actq_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
1519 		} else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutshutdown")) {
1520 			ruleset_dflt_toQShutdown = cnfparamvals[i].val.d.n;
1521 		} else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutactioncompletion")) {
1522 			ruleset_dflt_toActShutdown = cnfparamvals[i].val.d.n;
1523 		} else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutenqueue")) {
1524 			ruleset_dflt_toEnq = cnfparamvals[i].val.d.n;
1525 		} else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutworkerthreadshutdown")) {
1526 			ruleset_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
1527 		} else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.default")) {
1528 			dnscacheDefaultTTL = cnfparamvals[i].val.d.n;
1529 		} else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.enable")) {
1530 			dnscacheEnableTTL = cnfparamvals[i].val.d.n;
1531 		} else if(!strcmp(paramblk.descr[i].name, "parser.supportcompressionextension")) {
1532 			bSupportCompressionExtension = cnfparamvals[i].val.d.n;
1533 		} else {
1534 			dbgprintf("glblDoneLoadCnf: program error, non-handled "
1535 				"param '%s'\n", paramblk.descr[i].name);
1536 		}
1537 	}
1538 
1539 	if(glblDebugOnShutdown && Debug != DEBUG_FULL) {
1540 		Debug = DEBUG_ONDEMAND;
1541 		stddbg = -1;
1542 	}
1543 
1544 finalize_it:	RETiRet;
1545 }
1546 
1547 
1548 /* Initialize the glbl class. Must be called as the very first method
1549  * before anything else is called inside this class.
1550  * rgerhards, 2008-02-19
1551  */
1552 BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
1553 	/* request objects we use */
1554 	CHKiRet(objUse(prop, CORE_COMPONENT));
1555 
1556 	/* intialize properties */
1557 	storeLocalHostIPIF((uchar*)"127.0.0.1");
1558 
1559 	/* config handlers are never unregistered and need not be - we are always loaded ;) */
1560 	CHKiRet(regCfSysLineHdlr((uchar *)"debugfile", 0, eCmdHdlrGetWord, setDebugFile, NULL, NULL));
1561 	CHKiRet(regCfSysLineHdlr((uchar *)"debuglevel", 0, eCmdHdlrInt, setDebugLevel, NULL, NULL));
1562 	CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL));
1563 	CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL,
1564 	&bDropMalPTRMsgs, NULL));
1565 	CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr,
1566 	NULL));
1567 	CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL,
1568 	&pszDfltNetstrmDrvrCAF, NULL));
1569 	CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL,
1570 	&pszDfltNetstrmDrvrKeyFile, NULL));
1571 	CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL,
1572 	&pszDfltNetstrmDrvrCertFile, NULL));
1573 	CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL));
1574 	CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL));
1575 	CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrGoneAway, NULL, NULL, NULL));
1576 	CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL));
1577 	CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, legacySetMaxMessageSize, NULL, NULL));
1578 
1579 	/* Deprecated parser config options */
1580 	CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL,
1581 	&cCCEscapeChar, NULL));
1582 	CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL,
1583 	&bDropTrailingLF, NULL));
1584 	CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL,
1585 	&bEscapeCCOnRcv, NULL));
1586 	CHKiRet(regCfSysLineHdlr((uchar *)"spacelfonreceive", 0, eCmdHdlrBinary, NULL, &bSpaceLFOnRcv, NULL));
1587 	CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary, NULL,
1588 	&bEscape8BitChars, NULL));
1589 	CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, NULL, &bEscapeTab, NULL));
1590 
1591 	CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
1592 	resetConfigVariables, NULL, NULL));
1593 
1594 	INIT_ATOMIC_HELPER_MUT(mutTerminateInputs);
1595 ENDObjClassInit(glbl)
1596 
1597 
1598 /* Exit the glbl class.
1599  * rgerhards, 2008-04-17
1600  */
1601 BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
1602 	free(pszDfltNetstrmDrvr);
1603 	free(pszDfltNetstrmDrvrCAF);
1604 	free(pszDfltNetstrmDrvrKeyFile);
1605 	free(pszDfltNetstrmDrvrCertFile);
1606 	free(pszWorkDir);
1607 	free(LocalDomain);
1608 	free(LocalHostName);
1609 	free(LocalHostNameOverride);
1610 	free(oversizeMsgErrorFile);
1611 	free(LocalFQDNName);
1612 	freeTimezoneInfo();
1613 	objRelease(prop, CORE_COMPONENT);
1614 	if(propLocalHostNameToDelete != NULL)
1615 		prop.Destruct(&propLocalHostNameToDelete);
1616 	DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs);
1617 ENDObjClassExit(glbl)
1618