1 /* This is the main rsyslogd file.
2  * It contains code * that is known to be validly under ASL 2.0,
3  * because it was either written from scratch by me (rgerhards) or
4  * contributors who agreed to ASL 2.0.
5  *
6  * Copyright 2004-2019 Rainer Gerhards and Adiscon
7  *
8  * This file is part of rsyslog.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *       http://www.apache.org/licenses/LICENSE-2.0
15  *       -or-
16  *       see COPYING.ASL20 in the source distribution
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24 #include "config.h"
25 
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #ifdef ENABLE_LIBLOGGING_STDLOG
33 #  include <liblogging/stdlog.h>
34 #else
35 #  include <syslog.h>
36 #endif
37 #ifdef HAVE_LIBSYSTEMD
38 #	include <systemd/sd-daemon.h>
39 #endif
40 
41 #include "rsyslog.h"
42 #include "wti.h"
43 #include "ratelimit.h"
44 #include "parser.h"
45 #include "linkedlist.h"
46 #include "ruleset.h"
47 #include "action.h"
48 #include "iminternal.h"
49 #include "errmsg.h"
50 #include "threads.h"
51 #include "dnscache.h"
52 #include "prop.h"
53 #include "unicode-helper.h"
54 #include "net.h"
55 #include "glbl.h"
56 #include "debug.h"
57 #include "srUtils.h"
58 #include "rsconf.h"
59 #include "cfsysline.h"
60 #include "datetime.h"
61 #include "operatingstate.h"
62 #include "dirty.h"
63 #include "janitor.h"
64 #include "parserif.h"
65 
66 /* some global vars we need to differentiate between environments,
67  * for TZ-related things see
68  * https://github.com/rsyslog/rsyslog/issues/2994
69  */
70 static int runningInContainer = 0;
71 #ifdef OS_LINUX
72 static int emitTZWarning = 0;
73 #else
74 static int emitTZWarning = 1;
75 #endif
76 static pthread_t mainthread = 0;
77 
78 #if defined(_AIX)
79 /* AIXPORT : start
80  * The following includes and declarations are for support of the System
81  * Resource Controller (SRC) .
82  */
83 #include <sys/select.h>
84 /* AIXPORT : start*/
85 #define SRC_FD          13
86 #define SRCMSG          (sizeof(srcpacket))
87 
88 static void deinitAll(void);
89 #include <spc.h>
90 static  struct srcreq srcpacket;
91 int     cont;
92 struct  srchdr *srchdr;
93 char    progname[128];
94 
95 
96 /* Normally defined as locals in main
97  * But here since the functionality is split
98  * across multiple functions, we make it global
99  */
100 static int rc;
101 static socklen_t addrsz;
102 static struct sockaddr srcaddr;
103 int src_exists =  TRUE;
104 /* src end */
105 
106 /*
107  * SRC packet processing - .
108  */
109 #define SRCMIN(a, b)  (a < b) ? a : b
110 void
dosrcpacket(msgno,txt,len)111 dosrcpacket(msgno, txt, len)
112 	int msgno;
113 	char *txt;
114 	int len;
115 {
116 	struct srcrep reply;
117 
118 	reply.svrreply.rtncode = msgno;
119 /* AIXPORT :  srv was corrected to syslogd */
120 	strcpy(reply.svrreply.objname, "syslogd");
121 	snprintf(reply.svrreply.rtnmsg,
122 		SRCMIN(sizeof(reply.svrreply.rtnmsg)-1, strlen(txt)), "%s", txt);
123 	srchdr = srcrrqs((char *)&srcpacket);
124 	srcsrpy(srchdr, (char *)&reply, len, cont);
125 }
126 
127 #define  AIX_SRC_EXISTS_IF if(!src_exists) {
128 #define  AIX_SRC_EXISTS_FI   }
129 
aix_close_it(int i)130 static void aix_close_it(int i)
131 {
132 	if(src_exists) {
133 		if(i != SRC_FD)
134 			(void)close(i);
135 	} else
136 		close(i);
137 }
138 
139 
140 #else
141 
142 #define  AIX_SRC_EXISTS_IF
143 #define  AIX_SRC_EXISTS_FI
144 #define  aix_close_it(x) close(x)
145 #endif
146 
147 /* AIXPORT : end  */
148 
149 
150 DEFobjCurrIf(obj)
151 DEFobjCurrIf(prop)
152 DEFobjCurrIf(parser)
153 DEFobjCurrIf(ruleset)
154 DEFobjCurrIf(net)
155 DEFobjCurrIf(rsconf)
156 DEFobjCurrIf(module)
157 DEFobjCurrIf(datetime)
158 DEFobjCurrIf(glbl)
159 
160 extern int yydebug; /* interface to flex */
161 
162 
163 /* forward definitions */
164 void rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg);
165 void rsyslogdDoDie(int sig);
166 
167 
168 #ifndef PATH_PIDFILE
169 #if defined(_AIX)  /* AIXPORT : Add _AIX */
170 #	define PATH_PIDFILE "/etc/rsyslogd.pid"
171 #else
172 #	define PATH_PIDFILE "/var/run/rsyslogd.pid"
173 #endif /*_AIX*/
174 #endif
175 
176 #ifndef PATH_CONFFILE
177 #	define PATH_CONFFILE "/usr/local/etc/rsyslog.conf"
178 #endif
179 
180 /* global data items */
181 static int bChildDied;
182 static int bHadHUP;
183 static int doFork = 1; 	/* fork - run in daemon mode - read-only after startup */
184 int bFinished = 0;	/* used by termination signal handler, read-only except there
185 			 * is either 0 or the number of the signal that requested the
186 			 * termination.
187 			 */
188 const char *PidFile;
189 #define NO_PIDFILE "NONE"
190 int iConfigVerify = 0;	/* is this just a config verify run? */
191 rsconf_t *ourConf = NULL;	/* our config object */
192 int MarkInterval = 20 * 60;	/* interval between marks in seconds - read-only after startup */
193 ratelimit_t *dflt_ratelimiter = NULL; /* ratelimiter for submits without explicit one */
194 uchar *ConfFile = (uchar*) PATH_CONFFILE;
195 int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
196 			* If the main queue is either not yet ready or not running in
197 			* queueing mode (mode DIRECT!), then this is set to 0.
198 			*/
199 qqueue_t *pMsgQueue = NULL;	/* default main message queue */
200 prop_t *pInternalInputName = NULL;	/* there is only one global inputName for all internally-generated messages */
201 ratelimit_t *internalMsg_ratelimiter = NULL; /* ratelimiter for rsyslog-own messages */
202 int send_to_all = 0;   /* send message to all IPv4/IPv6 addresses */
203 
204 static struct queuefilenames_s {
205 	struct queuefilenames_s *next;
206 	uchar *name;
207 } *queuefilenames = NULL;
208 
209 
210 static __attribute__((noreturn)) void
rsyslogd_usage(void)211 rsyslogd_usage(void)
212 {
213 	fprintf(stderr, "usage: rsyslogd [options]\n"
214 			"use \"man rsyslogd\" for details. To run rsyslog "
215 			"interactively, use \"rsyslogd -n\"\n"
216 			"to run it in debug mode use \"rsyslogd -dn\"\n"
217 			"For further information see https://www.rsyslog.com/doc/\n");
218 	exit(1); /* "good" exit - done to terminate usage() */
219 }
220 
221 #ifndef HAVE_SETSID
222 extern void untty(void); /* in syslogd.c, GPLv3 */
223 static int
setsid(void)224 setsid(void)
225 {
226 	untty();
227 	return 0;
228 }
229 #endif
230 
231 
232 static rsRetVal
queryLocalHostname(void)233 queryLocalHostname(void)
234 {
235 	uchar *LocalHostName = NULL;
236 	uchar *LocalDomain = NULL;
237 	uchar *LocalFQDNName;
238 	DEFiRet;
239 
240 	CHKiRet(net.getLocalHostname(&LocalFQDNName));
241 	uchar *dot = (uchar*) strstr((char*)LocalFQDNName, ".");
242 	if(dot == NULL) {
243 		CHKmalloc(LocalHostName = (uchar*) strdup((char*)LocalFQDNName));
244 		CHKmalloc(LocalDomain = (uchar*)strdup(""));
245 	} else {
246 		const size_t lenhn = dot - LocalFQDNName;
247 		CHKmalloc(LocalHostName = (uchar*) strndup((char*) LocalFQDNName, lenhn));
248 		CHKmalloc(LocalDomain = (uchar*) strdup((char*) dot+1));
249 	}
250 
251 	glbl.SetLocalFQDNName(LocalFQDNName);
252 	glbl.SetLocalHostName(LocalHostName);
253 	glbl.SetLocalDomain(LocalDomain);
254 	glbl.GenerateLocalHostNameProperty();
255 	LocalHostName = NULL; /* handed over */
256 	LocalDomain = NULL; /* handed over */
257 
258 finalize_it:
259 	free(LocalHostName);
260 	free(LocalDomain);
261 	RETiRet;
262 }
263 
264 static rsRetVal
writePidFile(void)265 writePidFile(void)
266 {
267 	FILE *fp;
268 	DEFiRet;
269 
270 	const char *tmpPidFile;
271 
272 	if(!strcmp(PidFile, NO_PIDFILE)) {
273 		FINALIZE;
274 	}
275 	if(asprintf((char **)&tmpPidFile, "%s.tmp", PidFile) == -1) {
276 		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
277 	}
278 	if(tmpPidFile == NULL)
279 		tmpPidFile = PidFile;
280 	DBGPRINTF("rsyslogd: writing pidfile '%s'.\n", tmpPidFile);
281 	if((fp = fopen((char*) tmpPidFile, "w")) == NULL) {
282 		perror("rsyslogd: error writing pid file (creation stage)\n");
283 		ABORT_FINALIZE(RS_RET_ERR);
284 	}
285 	if(fprintf(fp, "%d", (int) glblGetOurPid()) < 0) {
286 		LogError(errno, iRet, "rsyslog: error writing pid file");
287 	}
288 	fclose(fp);
289 	if(tmpPidFile != PidFile) {
290 		if(rename(tmpPidFile, PidFile) != 0) {
291 			perror("rsyslogd: error writing pid file (rename stage)");
292 		}
293 		free((void*)tmpPidFile);
294 	}
295 finalize_it:
296 	RETiRet;
297 }
298 
299 /* duplicate startup protection: check, based on pid file, if our instance
300  * is already running. This MUST be called before we write our own pid file.
301  */
302 static rsRetVal
checkStartupOK(void)303 checkStartupOK(void)
304 {
305 	FILE *fp = NULL;
306 	DEFiRet;
307 
308 	DBGPRINTF("rsyslogd: checking if startup is ok, pidfile '%s'.\n", PidFile);
309 
310 	if(!strcmp(PidFile, NO_PIDFILE)) {
311 		dbgprintf("no pid file shall be written, skipping check\n");
312 		FINALIZE;
313 	}
314 
315 	if((fp = fopen((char*) PidFile, "r")) == NULL)
316 		FINALIZE; /* all well, no pid file yet */
317 
318 	int pf_pid;
319 	if(fscanf(fp, "%d", &pf_pid) != 1) {
320 		fprintf(stderr, "rsyslogd: error reading pid file, cannot start up\n");
321 		ABORT_FINALIZE(RS_RET_ERR);
322 	}
323 
324 	/* ok, we got a pid, let's check if the process is running */
325 	const pid_t pid = (pid_t) pf_pid;
326 	if(kill(pid, 0) == 0 || errno != ESRCH) {
327 		fprintf(stderr, "rsyslogd: pidfile '%s' and pid %d already exist.\n"
328 			"If you want to run multiple instances of rsyslog, you need "
329 			"to specify\n"
330 			"different pid files for them (-i option).\n",
331 			PidFile, (int) getpid());
332 		ABORT_FINALIZE(RS_RET_ERR);
333 	}
334 
335 finalize_it:
336 	if(fp != NULL)
337 		fclose(fp);
338 	RETiRet;
339 }
340 
341 /* prepares the background processes (if auto-backbrounding) for
342  * operation.
343  */
344 static void
prepareBackground(const int parentPipeFD)345 prepareBackground(const int parentPipeFD)
346 {
347 	DBGPRINTF("rsyslogd: in child, finalizing initialization\n");
348 
349 	dbgTimeoutToStderr = 0; /* we loose stderr when backgrounding! */
350 	int r = setsid();
351 	if(r == -1) {
352 		char err[1024];
353 		char em[2048];
354 		rs_strerror_r(errno, err, sizeof(err));
355 		snprintf(em, sizeof(em)-1, "rsyslog: error "
356 			                   "auto-backgrounding: %s\n", err);
357 		dbgprintf("%s\n", em);
358 		fprintf(stderr, "%s", em);
359 	}
360 
361 	int beginClose = 3;
362 
363 #ifdef HAVE_LIBSYSTEMD
364 	/* running under systemd? Then we must make sure we "forward" any
365 	 * fds passed by it (adjust the pid).
366 	 */
367 	if(sd_booted()) {
368 		const char *lstnPid = getenv("LISTEN_PID");
369 		if(lstnPid != NULL) {
370 			char szBuf[64];
371 			const int lstnPidI = atoi(lstnPid);
372 			snprintf(szBuf, sizeof(szBuf), "%d", lstnPidI);
373 			if(!strcmp(szBuf, lstnPid) && lstnPidI == getppid()) {
374 				snprintf(szBuf, sizeof(szBuf), "%d", (int) getpid());
375 				setenv("LISTEN_PID", szBuf, 1);
376 				/* ensure we do not close what systemd provided */
377 				const int nFds = sd_listen_fds(0);
378 				if(nFds > 0) {
379 					beginClose = SD_LISTEN_FDS_START + nFds;
380 				}
381 			}
382 		}
383 	}
384 #endif
385 
386 	/* close unnecessary open files */
387 	const int endClose = getdtablesize();
388 	close(0);
389 	for(int i = beginClose ; i <= endClose ; ++i) {
390 		if((i != dbgGetDbglogFd()) && (i != parentPipeFD)) {
391 			  aix_close_it(i); /* AIXPORT */
392 		}
393 	}
394 	seedRandomNumberForChild();
395 }
396 
397 /* This is called when rsyslog is set to auto-background itself. If so, a child
398  * is forked and the parent waits until it is initialized.
399  * The parent never returns from this function, only this happens for the child.
400  * So if it returns, you know you are in the child.
401  * return: file descriptor to which the child needs to write an "OK" or error
402  * message.
403  */
404 static int
forkRsyslog(void)405 forkRsyslog(void)
406 {
407 	int pipefd[2];
408 	pid_t cpid;
409 	char err[1024];
410 	char msgBuf[4096];
411 
412 	dbgprintf("rsyslogd: parent ready for forking\n");
413 	if(pipe(pipefd) == -1) {
414 		perror("error creating rsyslog \"fork pipe\" - terminating");
415 		exit(1);
416 	}
417 	AIX_SRC_EXISTS_IF /* AIXPORT */
418 	cpid = fork();
419 	if(cpid == -1) {
420 		perror("error forking rsyslogd process - terminating");
421 		exit(1);
422 	}
423 	AIX_SRC_EXISTS_FI /* AIXPORT */
424 
425 	if(cpid == 0) {
426 		prepareBackground(pipefd[1]);
427 		close(pipefd[0]);
428 		return pipefd[1];
429 	}
430 
431 	/* we are now in the parent. All we need to do here is wait for the
432 	 * startup message, emit it (if necessary) and then terminate.
433 	 */
434 	close(pipefd[1]);
435 	dbgprintf("rsyslogd: parent waiting up to 60 seconds to read startup message\n");
436 
437 	fd_set rfds;
438 	struct timeval tv;
439 	int retval;
440 
441 	FD_ZERO(&rfds);
442 	FD_SET(pipefd[0], &rfds);
443 	tv.tv_sec = 60;
444 	tv.tv_usec = 0;
445 
446 	retval = select(pipefd[0]+1, &rfds, NULL, NULL, &tv);
447 	if(retval == -1)
448 		rs_strerror_r(errno, err, sizeof(err));
449 	else
450 		strcpy(err, "OK");
451 	dbgprintf("rsyslogd: select() returns %d: %s\n", retval, err);
452 	if(retval == -1) {
453 		fprintf(stderr,"rsyslog startup failure, select() failed: %s\n", err);
454 		exit(1);
455 	} else if(retval == 0) {
456 		fprintf(stderr,"rsyslog startup failure, child did not "
457 			"respond within startup timeout (60 seconds)\n");
458 		exit(1);
459 	}
460 
461 	int nRead = read(pipefd[0], msgBuf, sizeof(msgBuf));
462 	if(nRead > 0) {
463 		msgBuf[nRead] = '\0';
464 	} else {
465 		rs_strerror_r(errno, err, sizeof(err));
466 		snprintf(msgBuf, sizeof(msgBuf)-1, "error reading \"fork pipe\": %s",
467 		         err);
468 	}
469 	if(strcmp(msgBuf, "OK")) {
470 		dbgprintf("rsyslog parent startup failure: %s\n", msgBuf);
471 		fprintf(stderr,"rsyslog startup failure: %s\n", msgBuf);
472 		exit(1);
473 	}
474 	close(pipefd[0]);
475 	dbgprintf("rsyslogd: parent terminates after successful child startup\n");
476 	exit(0);
477 }
478 
479 /* startup processing: this signals the waiting parent that the child is ready
480  * and the parent may terminate.
481  */
482 static void
tellChildReady(const int pipefd,const char * const msg)483 tellChildReady(const int pipefd, const char *const msg)
484 {
485 	dbgprintf("rsyslogd: child signaling OK\n");
486 	const int nWritten = write(pipefd, msg, strlen(msg));
487 	dbgprintf("rsyslogd: child signalled OK, nWritten %d\n", (int) nWritten);
488 	close(pipefd);
489 	sleep(1);
490 }
491 
492 /* print version and compile-time setting information */
493 static void
printVersion(void)494 printVersion(void)
495 {
496 	printf("rsyslogd  " VERSION " (aka %4d.%2.2d) compiled with:\n",
497 		2000 + VERSION_YEAR, VERSION_MONTH);
498 	printf("\tPLATFORM:\t\t\t\t%s\n", PLATFORM_ID);
499 	printf("\tPLATFORM (lsb_release -d):\t\t%s\n", PLATFORM_ID_LSB);
500 #ifdef FEATURE_REGEXP
501 	printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
502 #else
503 	printf("\tFEATURE_REGEXP:\t\t\t\tNo\n");
504 #endif
505 #if defined(SYSLOG_INET) && defined(USE_GSSAPI)
506 	printf("\tGSSAPI Kerberos 5 support:\t\tYes\n");
507 #else
508 	printf("\tGSSAPI Kerberos 5 support:\t\tNo\n");
509 #endif
510 #ifndef	NDEBUG
511 	printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
512 #else
513 	printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
514 #endif
515 #ifdef	HAVE_ATOMIC_BUILTINS
516 	printf("\t32bit Atomic operations supported:\tYes\n");
517 #else
518 	printf("\t32bit Atomic operations supported:\tNo\n");
519 #endif
520 #ifdef	HAVE_ATOMIC_BUILTINS64
521 	printf("\t64bit Atomic operations supported:\tYes\n");
522 #else
523 	printf("\t64bit Atomic operations supported:\tNo\n");
524 #endif
525 #ifdef	HAVE_JEMALLOC
526 	printf("\tmemory allocator:\t\t\tjemalloc\n");
527 #else
528 	printf("\tmemory allocator:\t\t\tsystem default\n");
529 #endif
530 #ifdef	RTINST
531 	printf("\tRuntime Instrumentation (slow code):\tYes\n");
532 #else
533 	printf("\tRuntime Instrumentation (slow code):\tNo\n");
534 #endif
535 #ifdef	USE_LIBUUID
536 	printf("\tuuid support:\t\t\t\tYes\n");
537 #else
538 	printf("\tuuid support:\t\t\t\tNo\n");
539 #endif
540 #ifdef HAVE_LIBSYSTEMD
541 	printf("\tsystemd support:\t\t\tYes\n");
542 #else
543 	printf("\tsystemd support:\t\t\tNo\n");
544 #endif
545 	/* we keep the following message to so that users don't need
546 	 * to wonder.
547 	 */
548 	printf("\tConfig file:\t\t\t\t" PATH_CONFFILE "\n");
549 	printf("\tPID file:\t\t\t\t" PATH_PIDFILE "%s\n", PATH_PIDFILE[0]!='/'?
550 			"(relative to global workingdirectory)":"");
551 	printf("\tNumber of Bits in RainerScript integers: 64\n");
552 	printf("\nSee https://www.rsyslog.com for more information.\n");
553 }
554 
555 static rsRetVal
rsyslogd_InitStdRatelimiters(void)556 rsyslogd_InitStdRatelimiters(void)
557 {
558 	DEFiRet;
559 	CHKiRet(ratelimitNew(&dflt_ratelimiter, "rsyslogd", "dflt"));
560 	CHKiRet(ratelimitNew(&internalMsg_ratelimiter, "rsyslogd", "internal_messages"));
561 	ratelimitSetThreadSafe(internalMsg_ratelimiter);
562 	ratelimitSetLinuxLike(internalMsg_ratelimiter, glblIntMsgRateLimitItv, glblIntMsgRateLimitBurst);
563 	/* TODO: make internalMsg ratelimit settings configurable */
564 finalize_it:
565 	RETiRet;
566 }
567 
568 
569 /* Method to initialize all global classes and use the objects that we need.
570  * rgerhards, 2008-01-04
571  * rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime
572  */
573 static rsRetVal
rsyslogd_InitGlobalClasses(void)574 rsyslogd_InitGlobalClasses(void)
575 {
576 	DEFiRet;
577 	const char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */
578 
579 	/* Intialize the runtime system */
580 	pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */
581 	CHKiRet(rsrtInit(&pErrObj, &obj));
582 	rsrtSetErrLogger(rsyslogd_submitErrMsg);
583 
584 	/* Now tell the system which classes we need ourselfs */
585 	pErrObj = "glbl";
586 	CHKiRet(objUse(glbl,     CORE_COMPONENT));
587 	pErrObj = "module";
588 	CHKiRet(objUse(module,   CORE_COMPONENT));
589 	pErrObj = "datetime";
590 	CHKiRet(objUse(datetime, CORE_COMPONENT));
591 	pErrObj = "ruleset";
592 	CHKiRet(objUse(ruleset,  CORE_COMPONENT));
593 	pErrObj = "prop";
594 	CHKiRet(objUse(prop,     CORE_COMPONENT));
595 	pErrObj = "parser";
596 	CHKiRet(objUse(parser,     CORE_COMPONENT));
597 	pErrObj = "rsconf";
598 	CHKiRet(objUse(rsconf,     CORE_COMPONENT));
599 
600 	/* intialize some dummy classes that are not part of the runtime */
601 	pErrObj = "action";
602 	CHKiRet(actionClassInit());
603 	pErrObj = "template";
604 	CHKiRet(templateInit());
605 
606 	/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
607 	pErrObj = "net";
608 	CHKiRet(objUse(net, LM_NET_FILENAME));
609 
610 	dnscacheInit();
611 	initRainerscript();
612 	ratelimitModInit();
613 
614 	/* we need to create the inputName property (only once during our lifetime) */
615 	CHKiRet(prop.Construct(&pInternalInputName));
616 	CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd") - 1));
617 	CHKiRet(prop.ConstructFinalize(pInternalInputName));
618 
619 finalize_it:
620 	if(iRet != RS_RET_OK) {
621 		/* we know we are inside the init sequence, so we can safely emit
622 		 * messages to stderr. -- rgerhards, 2008-04-02
623 		 */
624 		fprintf(stderr, "Error during class init for object '%s' - failing...\n", pErrObj);
625 		fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n"
626 				"Did you do a \"make install\"?\n"
627 				"Suggested action: run rsyslogd with -d -n options to see what exactly "
628 				"fails.\n");
629 	}
630 
631 	RETiRet;
632 }
633 
634 /* preprocess a batch of messages, that is ready them for actual processing. This is done
635  * as a first stage and totally in parallel to any other worker active in the system. So
636  * it helps us keep up the overall concurrency level.
637  * rgerhards, 2010-06-09
638  */
639 static rsRetVal
preprocessBatch(batch_t * pBatch,int * pbShutdownImmediate)640 preprocessBatch(batch_t *pBatch, int *pbShutdownImmediate) {
641 	prop_t *ip;
642 	prop_t *fqdn;
643 	prop_t *localName;
644 	int bIsPermitted;
645 	smsg_t *pMsg;
646 	int i;
647 	rsRetVal localRet;
648 	DEFiRet;
649 
650 	for(i = 0 ; i < pBatch->nElem  && !*pbShutdownImmediate ; i++) {
651 		pMsg = pBatch->pElem[i].pMsg;
652 		if((pMsg->msgFlags & NEEDS_ACLCHK_U) != 0) {
653 			DBGPRINTF("msgConsumer: UDP ACL must be checked for message (hostname-based)\n");
654 			if(net.cvthname(pMsg->rcvFrom.pfrominet, &localName, &fqdn, &ip) != RS_RET_OK)
655 				continue;
656 			bIsPermitted = net.isAllowedSender2((uchar*)"UDP",
657 			    (struct sockaddr *)pMsg->rcvFrom.pfrominet, (char*)propGetSzStr(fqdn), 1);
658 			if(!bIsPermitted) {
659 				DBGPRINTF("Message from '%s' discarded, not a permitted sender host\n",
660 					  propGetSzStr(fqdn));
661 				pBatch->eltState[i] = BATCH_STATE_DISC;
662 			} else {
663 				/* save some of the info we obtained */
664 				MsgSetRcvFrom(pMsg, localName);
665 				CHKiRet(MsgSetRcvFromIP(pMsg, ip));
666 				pMsg->msgFlags &= ~NEEDS_ACLCHK_U;
667 			}
668 		}
669 		if((pMsg->msgFlags & NEEDS_PARSING) != 0) {
670 			if((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK)  {
671 				DBGPRINTF("Message discarded, parsing error %d\n", localRet);
672 				pBatch->eltState[i] = BATCH_STATE_DISC;
673 			}
674 		}
675 	}
676 
677 finalize_it:
678 	RETiRet;
679 }
680 
681 
682 /* The consumer of dequeued messages. This function is called by the
683  * queue engine on dequeueing of a message. It runs on a SEPARATE
684  * THREAD. It receives an array of pointers, which it must iterate
685  * over. We do not do any further batching, as this is of no benefit
686  * for the main queue.
687  */
688 static rsRetVal
msgConsumer(void * notNeeded,batch_t * pBatch,wti_t * pWti)689 msgConsumer(void __attribute__((unused)) *notNeeded, batch_t *pBatch, wti_t *pWti)
690 {
691 	DEFiRet;
692 	assert(pBatch != NULL);
693 	preprocessBatch(pBatch, pWti->pbShutdownImmediate);
694 	ruleset.ProcessBatch(pBatch, pWti);
695 //TODO: the BATCH_STATE_COMM must be set somewhere down the road, but we
696 //do not have this yet and so we emulate -- 2010-06-10
697 int i;
698 	for(i = 0 ; i < pBatch->nElem  && !*pWti->pbShutdownImmediate ; i++) {
699 		pBatch->eltState[i] = BATCH_STATE_COMM;
700 	}
701 	RETiRet;
702 }
703 
704 
705 /* create a main message queue, now also used for ruleset queues. This function
706  * needs to be moved to some other module, but it is considered acceptable for
707  * the time being (remember that we want to restructure config processing at large!).
708  * rgerhards, 2009-10-27
709  */
createMainQueue(qqueue_t ** ppQueue,uchar * pszQueueName,struct nvlst * lst)710 rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName, struct nvlst *lst)
711 {
712 	struct queuefilenames_s *qfn;
713 	uchar *qfname = NULL;
714 	static int qfn_renamenum = 0;
715 	uchar qfrenamebuf[1024];
716 	DEFiRet;
717 
718 	/* create message queue */
719 	CHKiRet_Hdlr(qqueueConstruct(ppQueue, ourConf->globals.mainQ.MainMsgQueType,
720 	ourConf->globals.mainQ.iMainMsgQueueNumWorkers, ourConf->globals.mainQ.iMainMsgQueueSize, msgConsumer)) {
721 		/* no queue is fatal, we need to give up in that case... */
722 		LogError(0, iRet, "could not create (ruleset) main message queue"); \
723 	}
724 	/* name our main queue object (it's not fatal if it fails...) */
725 	obj.SetName((obj_t*) (*ppQueue), pszQueueName);
726 
727 	if(lst == NULL) { /* use legacy parameters? */
728 		/* ... set some properties ... */
729 	#	define setQPROP(func, directive, data) \
730 		CHKiRet_Hdlr(func(*ppQueue, data)) { \
731 			LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, " \
732 			"running with default setting", iRet); \
733 		}
734 	#	define setQPROPstr(func, directive, data) \
735 		CHKiRet_Hdlr(func(*ppQueue, data, (data == NULL)? 0 : strlen((char*) data))) { \
736 			LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, " \
737 			"running with default setting", iRet); \
738 		}
739 
740 		if(ourConf->globals.mainQ.pszMainMsgQFName != NULL) {
741 			/* check if the queue file name is unique, else emit an error */
742 			for(qfn = queuefilenames ; qfn != NULL ; qfn = qfn->next) {
743 				dbgprintf("check queue file name '%s' vs '%s'\n", qfn->name,
744 					ourConf->globals.mainQ.pszMainMsgQFName );
745 				if(!ustrcmp(qfn->name, ourConf->globals.mainQ.pszMainMsgQFName)) {
746 					snprintf((char*)qfrenamebuf, sizeof(qfrenamebuf), "%d-%s-%s",
747 						 ++qfn_renamenum, ourConf->globals.mainQ.pszMainMsgQFName,
748 						 (pszQueueName == NULL) ? "NONAME" : (char*)pszQueueName);
749 					qfname = ustrdup(qfrenamebuf);
750 					LogError(0, NO_ERRCODE, "Error: queue file name '%s' already in use "
751 						" - using '%s' instead", ourConf->globals.mainQ.pszMainMsgQFName,
752 						qfname);
753 					break;
754 				}
755 			}
756 			if(qfname == NULL)
757 				qfname = ustrdup(ourConf->globals.mainQ.pszMainMsgQFName);
758 			qfn = malloc(sizeof(struct queuefilenames_s));
759 			qfn->name = qfname;
760 			qfn->next = queuefilenames;
761 			queuefilenames = qfn;
762 		}
763 
764 		setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize",
765 			ourConf->globals.mainQ.iMainMsgQueMaxFileSize);
766 		setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace",
767 			ourConf->globals.mainQ.iMainMsgQueMaxDiskSpace);
768 		setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize",
769 			ourConf->globals.mainQ.iMainMsgQueDeqBatchSize);
770 		setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", qfname);
771 		setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval",
772 			ourConf->globals.mainQ.iMainMsgQPersistUpdCnt);
773 		setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles",
774 			ourConf->globals.mainQ.bMainMsgQSyncQeueFiles);
775 		setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown",
776 			ourConf->globals.mainQ.iMainMsgQtoQShutdown );
777 		setQPROP(qqueueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion",
778 			ourConf->globals.mainQ.iMainMsgQtoActShutdown);
779 		setQPROP(qqueueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown",
780 			ourConf->globals.mainQ.iMainMsgQtoWrkShutdown);
781 		setQPROP(qqueueSettoEnq, "$MainMsgQueueTimeoutEnqueue", ourConf->globals.mainQ.iMainMsgQtoEnq);
782 		setQPROP(qqueueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark",
783 			ourConf->globals.mainQ.iMainMsgQHighWtrMark);
784 		setQPROP(qqueueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark",
785 			ourConf->globals.mainQ.iMainMsgQLowWtrMark);
786 		setQPROP(qqueueSetiDiscardMrk, "$MainMsgQueueDiscardMark",
787 			ourConf->globals.mainQ.iMainMsgQDiscardMark);
788 		setQPROP(qqueueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity",
789 			ourConf->globals.mainQ.iMainMsgQDiscardSeverity);
790 		setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages",
791 			ourConf->globals.mainQ.iMainMsgQWrkMinMsgs);
792 		setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown",
793 			ourConf->globals.mainQ.bMainMsgQSaveOnShutdown);
794 		setQPROP(qqueueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown",
795 			ourConf->globals.mainQ.iMainMsgQDeqSlowdown);
796 		setQPROP(qqueueSetiDeqtWinFromHr,  "$MainMsgQueueDequeueTimeBegin",
797 			ourConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr);
798 		setQPROP(qqueueSetiDeqtWinToHr,    "$MainMsgQueueDequeueTimeEnd",
799 			ourConf->globals.mainQ.iMainMsgQueueDeqtWinToHr);
800 
801 	#	undef setQPROP
802 	#	undef setQPROPstr
803 	} else { /* use new style config! */
804 		qqueueSetDefaultsRulesetQueue(*ppQueue);
805 		qqueueApplyCnfParam(*ppQueue, lst);
806 	}
807 	RETiRet;
808 }
809 
810 rsRetVal
startMainQueue(qqueue_t * const pQueue)811 startMainQueue(qqueue_t *const pQueue)
812 {
813 	DEFiRet;
814 	CHKiRet_Hdlr(qqueueStart(pQueue)) {
815 		/* no queue is fatal, we need to give up in that case... */
816 		LogError(0, iRet, "could not start (ruleset) main message queue");
817 		pQueue->qType = QUEUETYPE_DIRECT;
818 		CHKiRet_Hdlr(qqueueStart(pQueue)) {
819 			/* no queue is fatal, we need to give up in that case... */
820 			LogError(0, iRet, "fatal error: could not even start queue in direct mode");
821 		}
822 	}
823 	RETiRet;
824 }
825 
826 
827 /* this is a special function used to submit an error message. This
828  * function is also passed to the runtime library as the generic error
829  * message handler. -- rgerhards, 2008-04-17
830  */
831 void
rsyslogd_submitErrMsg(const int severity,const int iErr,const uchar * msg)832 rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg)
833 {
834 	if (glbl.GetGlobalInputTermState() == 1) {
835 		/* After fork the stderr is unusable (dfltErrLogger uses is internally) */
836 		if(!doFork)
837 			dfltErrLogger(severity, iErr, msg);
838 	} else {
839 		logmsgInternal(iErr, LOG_SYSLOG|(severity & 0x07), msg, 0);
840 	}
841 }
842 
843 static inline rsRetVal
submitMsgWithDfltRatelimiter(smsg_t * pMsg)844 submitMsgWithDfltRatelimiter(smsg_t *pMsg)
845 {
846 	return ratelimitAddMsg(dflt_ratelimiter, NULL, pMsg);
847 }
848 
849 
850 static void
logmsgInternal_doWrite(smsg_t * pMsg)851 logmsgInternal_doWrite(smsg_t *pMsg)
852 {
853 	const int pri = getPRIi(pMsg);
854 	if(pri % 8 <= glblIntMsgsSeverityFilter) {
855 		if(bProcessInternalMessages) {
856 			submitMsg2(pMsg);
857 			pMsg = NULL; /* msg obj handed over; do not destruct */
858 		} else {
859 			uchar *const msg = getMSG(pMsg);
860 			#ifdef ENABLE_LIBLOGGING_STDLOG
861 			/* the "emit only once" rate limiter is quick and dirty and not
862 			 * thread safe. However, that's no problem for the current intend
863 			 * and it is not justified to create more robust code for the
864 			 * functionality. -- rgerhards, 2018-05-14
865 			 */
866 			static warnmsg_emitted = 0;
867 			if(warnmsg_emitted == 0) {
868 				stdlog_log(stdlog_hdl, LOG_WARNING, "%s",
869 					"RSYSLOG WARNING: liblogging-stdlog "
870 					"functionality will go away soon. For details see "
871 					"https://github.com/rsyslog/rsyslog/issues/2706");
872 				warnmsg_emitted = 1;
873 			}
874 			stdlog_log(stdlog_hdl, pri2sev(pri), "%s", (char*)msg);
875 			#else
876 			syslog(pri, "%s", msg);
877 			#endif
878 		}
879 	}
880 	if(pMsg != NULL) {
881 		msgDestruct(&pMsg);
882 	}
883 }
884 
885 /* This function creates a log message object out of the provided
886  * message text and forwards it for logging.
887  */
888 static rsRetVal
logmsgInternalSubmit(const int iErr,const syslog_pri_t pri,const size_t lenMsg,const char * __restrict__ const msg,int flags)889 logmsgInternalSubmit(const int iErr, const syslog_pri_t pri, const size_t lenMsg,
890 	const char *__restrict__ const msg, int flags)
891 {
892 	uchar pszTag[33];
893 	smsg_t *pMsg;
894 	DEFiRet;
895 
896 	CHKiRet(msgConstruct(&pMsg));
897 	MsgSetInputName(pMsg, pInternalInputName);
898 	MsgSetRawMsg(pMsg, (char*)msg, lenMsg);
899 	MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
900 	MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
901 	MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
902 	MsgSetMSGoffs(pMsg, 0);
903 	/* check if we have an error code associated and, if so,
904 	 * adjust the tag. -- rgerhards, 2008-06-27
905 	 */
906 	if(iErr == NO_ERRCODE) {
907 		MsgSetTAG(pMsg, UCHAR_CONSTANT("rsyslogd:"), sizeof("rsyslogd:") - 1);
908 	} else {
909 		size_t len = snprintf((char*)pszTag, sizeof(pszTag), "rsyslogd%d:", iErr);
910 		pszTag[32] = '\0'; /* just to make sure... */
911 		MsgSetTAG(pMsg, pszTag, len);
912 	}
913 	flags |= INTERNAL_MSG;
914 	pMsg->msgFlags  = flags;
915 	msgSetPRI(pMsg, pri);
916 
917 	iminternalAddMsg(pMsg);
918 finalize_it:
919 	RETiRet;
920 }
921 
922 
923 
924 /* rgerhards 2004-11-09: the following is a function that can be used
925  * to log a message orginating from the syslogd itself.
926  */
927 rsRetVal
logmsgInternal(int iErr,const syslog_pri_t pri,const uchar * const msg,int flags)928 logmsgInternal(int iErr, const syslog_pri_t pri, const uchar *const msg, int flags)
929 {
930 	size_t lenMsg;
931 	unsigned i;
932 	char *bufModMsg = NULL; /* buffer for modified message, should we need to modify */
933 	DEFiRet;
934 
935 	/* we first do a path the remove control characters that may have accidently
936 	 * introduced (program error!). This costs performance, but we do not expect
937 	 * to be called very frequently in any case ;) -- rgerhards, 2013-12-19.
938 	 */
939 	lenMsg = ustrlen(msg);
940 	for(i = 0 ; i < lenMsg ; ++i) {
941 		if(msg[i] < 0x20 || msg[i] == 0x7f) {
942 			if(bufModMsg == NULL) {
943 				CHKmalloc(bufModMsg = strdup((char*) msg));
944 			}
945 			bufModMsg[i] = ' ';
946 		}
947 	}
948 
949 	CHKiRet(logmsgInternalSubmit(iErr, pri, lenMsg,
950 				   (bufModMsg == NULL) ? (char*)msg : bufModMsg,
951 				   flags));
952 
953 	/* we now check if we should print internal messages out to stderr. This was
954 	 * suggested by HKS as a way to help people troubleshoot rsyslog configuration
955 	 * (by running it interactively. This makes an awful lot of sense, so I add
956 	 * it here. -- rgerhards, 2008-07-28
957 	 * Note that error messages can not be disabled during a config verify. This
958 	 * permits us to process unmodified config files which otherwise contain a
959 	 * supressor statement.
960 	 */
961 	int emit_to_stderr = (ourConf == NULL) ? 1 : ourConf->globals.bErrMsgToStderr;
962 	int emit_supress_msg = 0;
963 	if(Debug == DEBUG_FULL || !doFork) {
964 		emit_to_stderr = 1;
965 	}
966 	if(ourConf != NULL && ourConf->globals.maxErrMsgToStderr != -1) {
967 		if(emit_to_stderr && ourConf->globals.maxErrMsgToStderr != -1 && ourConf->globals.maxErrMsgToStderr) {
968 			--ourConf->globals.maxErrMsgToStderr;
969 			if(ourConf->globals.maxErrMsgToStderr == 0)
970 				emit_supress_msg = 1;
971 		} else {
972 			emit_to_stderr = 0;
973 		}
974 	}
975 	if(emit_to_stderr || iConfigVerify) {
976 		if(pri2sev(pri) == LOG_ERR)
977 			fprintf(stderr, "rsyslogd: %s\n",
978 				(bufModMsg == NULL) ? (char*)msg : bufModMsg);
979 	}
980 	if(emit_supress_msg) {
981 		fprintf(stderr, "rsyslogd: configured max number of error messages "
982 			"to stderr reached, further messages will not be output\n"
983 			"Consider adjusting\n"
984 			"    global(errorMessagesToStderr.maxNumber=\"xx\")\n"
985 			"if you want more.\n");
986 	}
987 
988 finalize_it:
989 	free(bufModMsg);
990 	RETiRet;
991 }
992 
993 rsRetVal
submitMsg(smsg_t * pMsg)994 submitMsg(smsg_t *pMsg)
995 {
996 	return submitMsgWithDfltRatelimiter(pMsg);
997 }
998 
999 
ATTR_NONNULL()1000 static rsRetVal ATTR_NONNULL()
1001 splitOversizeMessage(smsg_t *const pMsg)
1002 {
1003 	DEFiRet;
1004 	const char *rawmsg;
1005 	int nsegments;
1006 	int len_rawmsg;
1007 	const int maxlen = glblGetMaxLine();
1008 	ISOBJ_TYPE_assert(pMsg, msg);
1009 
1010 	getRawMsg(pMsg, (uchar**) &rawmsg, &len_rawmsg);
1011 	nsegments = len_rawmsg / maxlen;
1012 	const int len_last_segment = len_rawmsg % maxlen;
1013 	DBGPRINTF("splitting oversize message, size %d, segment size %d, "
1014 		"nsegments %d, bytes in last fragment %d\n",
1015 		len_rawmsg, maxlen, nsegments, len_last_segment);
1016 
1017 	smsg_t *pMsg_seg;
1018 
1019 	/* process full segments */
1020 	for(int i = 0 ; i < nsegments ; ++i) {
1021 		CHKmalloc(pMsg_seg = MsgDup(pMsg));
1022 		MsgSetRawMsg(pMsg_seg, rawmsg + (i * maxlen), maxlen);
1023 		submitMsg2(pMsg_seg);
1024 	}
1025 
1026 	/* if necessary, write partial last segment */
1027 	if(len_last_segment != 0) {
1028 		CHKmalloc(pMsg_seg = MsgDup(pMsg));
1029 		MsgSetRawMsg(pMsg_seg, rawmsg + (nsegments * maxlen), len_last_segment);
1030 		submitMsg2(pMsg_seg);
1031 	}
1032 
1033 finalize_it:
1034 	RETiRet;
1035 }
1036 
1037 
1038 /* submit a message to the main message queue.   This is primarily
1039  * a hook to prevent the need for callers to know about the main message queue
1040  * rgerhards, 2008-02-13
1041  */
1042 rsRetVal
submitMsg2(smsg_t * pMsg)1043 submitMsg2(smsg_t *pMsg)
1044 {
1045 	qqueue_t *pQueue;
1046 	ruleset_t *pRuleset;
1047 	DEFiRet;
1048 
1049 	ISOBJ_TYPE_assert(pMsg, msg);
1050 
1051 	if(getRawMsgLen(pMsg) > glblGetMaxLine()){
1052 		uchar *rawmsg;
1053 		int dummy;
1054 		getRawMsg(pMsg, &rawmsg, &dummy);
1055 		if(glblReportOversizeMessage()) {
1056 			LogMsg(0, RS_RET_OVERSIZE_MSG, LOG_WARNING,
1057 				"message too long (%d) with configured size %d, begin of "
1058 				"message is: %.80s",
1059 				getRawMsgLen(pMsg), glblGetMaxLine(), rawmsg);
1060 		}
1061 		writeOversizeMessageLog(pMsg);
1062 		if(glblGetOversizeMsgInputMode() == glblOversizeMsgInputMode_Split) {
1063 			splitOversizeMessage(pMsg);
1064 			/* we have submitted the message segments recursively, so we
1065 			 * can just deleted the original msg object and terminate.
1066 			 */
1067 			msgDestruct(&pMsg);
1068 			FINALIZE;
1069 		} else if(glblGetOversizeMsgInputMode() == glblOversizeMsgInputMode_Truncate) {
1070 			MsgTruncateToMaxSize(pMsg);
1071 		} else {
1072 			/* in "accept" mode, we do nothing, simply because "accept" means
1073 			 * to use as-is.
1074 			 */
1075 			assert(glblGetOversizeMsgInputMode() == glblOversizeMsgInputMode_Accept);
1076 		}
1077 	}
1078 
1079 	pRuleset = MsgGetRuleset(pMsg);
1080 	pQueue = (pRuleset == NULL) ? pMsgQueue : ruleset.GetRulesetQueue(pRuleset);
1081 
1082 	/* if a plugin logs a message during shutdown, the queue may no longer exist */
1083 	if(pQueue == NULL) {
1084 		DBGPRINTF("submitMsg2() could not submit message - "
1085 			  "queue does (no longer?) exist - ignored\n");
1086 		FINALIZE;
1087 	}
1088 
1089 	qqueueEnqMsg(pQueue, pMsg->flowCtlType, pMsg);
1090 
1091 finalize_it:
1092 	RETiRet;
1093 }
1094 
1095 /* submit multiple messages at once, very similar to submitMsg, just
1096  * for multi_submit_t. All messages need to go into the SAME queue!
1097  * rgerhards, 2009-06-16
1098  */
ATTR_NONNULL()1099 rsRetVal ATTR_NONNULL()
1100 multiSubmitMsg2(multi_submit_t *const pMultiSub)
1101 {
1102 	qqueue_t *pQueue;
1103 	ruleset_t *pRuleset;
1104 	DEFiRet;
1105 
1106 	if(pMultiSub->nElem == 0)
1107 		FINALIZE;
1108 
1109 	pRuleset = MsgGetRuleset(pMultiSub->ppMsgs[0]);
1110 	pQueue = (pRuleset == NULL) ? pMsgQueue : ruleset.GetRulesetQueue(pRuleset);
1111 
1112 	/* if a plugin logs a message during shutdown, the queue may no longer exist */
1113 	if(pQueue == NULL) {
1114 		DBGPRINTF("multiSubmitMsg() could not submit message - "
1115 			  "queue does (no longer?) exist - ignored\n");
1116 		FINALIZE;
1117 	}
1118 
1119 	iRet = pQueue->MultiEnq(pQueue, pMultiSub);
1120 	pMultiSub->nElem = 0;
1121 
1122 finalize_it:
1123 	RETiRet;
1124 }
1125 rsRetVal
multiSubmitMsg(multi_submit_t * pMultiSub)1126 multiSubmitMsg(multi_submit_t *pMultiSub) /* backward compat. level */
1127 {
1128 	return multiSubmitMsg2(pMultiSub);
1129 }
1130 
1131 
1132 /* flush multiSubmit, e.g. at end of read records */
1133 rsRetVal
multiSubmitFlush(multi_submit_t * pMultiSub)1134 multiSubmitFlush(multi_submit_t *pMultiSub)
1135 {
1136 	DEFiRet;
1137 	if(pMultiSub->nElem > 0) {
1138 		iRet = multiSubmitMsg2(pMultiSub);
1139 	}
1140 	RETiRet;
1141 }
1142 
1143 
1144 /* some support for command line option parsing. Any non-trivial options must be
1145  * buffered until the complete command line has been parsed. This is necessary to
1146  * prevent dependencies between the options. That, in turn, means we need to have
1147  * something that is capable of buffering options and there values. The follwing
1148  * functions handle that.
1149  * rgerhards, 2008-04-04
1150  */
1151 typedef struct bufOpt {
1152 	struct bufOpt *pNext;
1153 	char optchar;
1154 	char *arg;
1155 } bufOpt_t;
1156 static bufOpt_t *bufOptRoot = NULL;
1157 static bufOpt_t *bufOptLast = NULL;
1158 
1159 /* add option buffer */
1160 static rsRetVal
bufOptAdd(char opt,char * arg)1161 bufOptAdd(char opt, char *arg)
1162 {
1163 	DEFiRet;
1164 	bufOpt_t *pBuf;
1165 
1166 	if((pBuf = malloc(sizeof(bufOpt_t))) == NULL)
1167 		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
1168 
1169 	pBuf->optchar = opt;
1170 	pBuf->arg = arg;
1171 	pBuf->pNext = NULL;
1172 
1173 	if(bufOptLast == NULL) {
1174 		bufOptRoot = pBuf; /* then there is also no root! */
1175 	} else {
1176 		bufOptLast->pNext = pBuf;
1177 	}
1178 	bufOptLast = pBuf;
1179 
1180 finalize_it:
1181 	RETiRet;
1182 }
1183 
1184 
1185 /* remove option buffer from top of list, return values and destruct buffer itself.
1186  * returns RS_RET_END_OF_LINKEDLIST when no more options are present.
1187  * (we use int *opt instead of char *opt to keep consistent with getopt())
1188  */
1189 static rsRetVal
bufOptRemove(int * opt,char ** arg)1190 bufOptRemove(int *opt, char **arg)
1191 {
1192 	DEFiRet;
1193 	bufOpt_t *pBuf;
1194 
1195 	if(bufOptRoot == NULL)
1196 		ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST);
1197 	pBuf = bufOptRoot;
1198 
1199 	*opt = pBuf->optchar;
1200 	*arg = pBuf->arg;
1201 
1202 	bufOptRoot = pBuf->pNext;
1203 	free(pBuf);
1204 
1205 finalize_it:
1206 	RETiRet;
1207 }
1208 
1209 
1210 static void
hdlr_sigttin_ou(void)1211 hdlr_sigttin_ou(void)
1212 {
1213 	/* this is just a dummy to care for our sigttin input
1214 	 * module cancel interface and sigttou internal message
1215 	 * notificaton/mainloop wakeup mechanism. The important
1216 	 * point is that it actually does *NOTHING*.
1217 	 */
1218 }
1219 
1220 static void
hdlr_enable(int sig,void (* hdlr)())1221 hdlr_enable(int sig, void (*hdlr)())
1222 {
1223 	struct sigaction sigAct;
1224 	memset(&sigAct, 0, sizeof (sigAct));
1225 	sigemptyset(&sigAct.sa_mask);
1226 	sigAct.sa_handler = hdlr;
1227 	sigaction(sig, &sigAct, NULL);
1228 }
1229 
1230 static void
hdlr_sighup(void)1231 hdlr_sighup(void)
1232 {
1233 	bHadHUP = 1;
1234 	/* at least on FreeBSD we seem not to necessarily awake the main thread.
1235 	 * So let's do it explicitely.
1236 	 */
1237 	dbgprintf("awaking mainthread on HUP\n");
1238 	pthread_kill(mainthread, SIGTTIN);
1239 }
1240 
1241 static void
hdlr_sigchld(void)1242 hdlr_sigchld(void)
1243 {
1244 	bChildDied = 1;
1245 }
1246 
1247 static void
rsyslogdDebugSwitch(void)1248 rsyslogdDebugSwitch(void)
1249 {
1250 	time_t tTime;
1251 	struct tm tp;
1252 
1253 	datetime.GetTime(&tTime);
1254 	localtime_r(&tTime, &tp);
1255 	if(debugging_on == 0) {
1256 		debugging_on = 1;
1257 		dbgprintf("\n");
1258 		dbgprintf("\n");
1259 		dbgprintf("********************************************************************************\n");
1260 		dbgprintf("Switching debugging_on to true at %2.2d:%2.2d:%2.2d\n",
1261 			  tp.tm_hour, tp.tm_min, tp.tm_sec);
1262 		dbgprintf("********************************************************************************\n");
1263 	} else {
1264 		dbgprintf("********************************************************************************\n");
1265 		dbgprintf("Switching debugging_on to false at %2.2d:%2.2d:%2.2d\n",
1266 			  tp.tm_hour, tp.tm_min, tp.tm_sec);
1267 		dbgprintf("********************************************************************************\n");
1268 		dbgprintf("\n");
1269 		dbgprintf("\n");
1270 		debugging_on = 0;
1271 	}
1272 }
1273 
1274 
1275 /* This is the main entry point into rsyslogd. Over time, we should try to
1276  * modularize it a bit more...
1277  *
1278  * NOTE on stderr and stdout: they are kept open during a fork. Note that this
1279  * may introduce subtle security issues: if we are in a jail, one may break out of
1280  * it via these descriptors. But if I close them earlier, error messages will (once
1281  * again) not be emitted to the user that starts the daemon. Given that the risk
1282  * of a break-in is very low in the startup phase, we decide it is more important
1283  * to emit error messages.
1284  */
1285 static void
initAll(int argc,char ** argv)1286 initAll(int argc, char **argv)
1287 {
1288 	rsRetVal localRet;
1289 	int ch;
1290 	int iHelperUOpt;
1291 	int bChDirRoot = 1; /* change the current working directory to "/"? */
1292 	char *arg;	/* for command line option processing */
1293 	char cwdbuf[128]; /* buffer to obtain/display current working directory */
1294 	int parentPipeFD = 0; /* fd of pipe to parent, if auto-backgrounding */
1295 	DEFiRet;
1296 
1297 	/* prepare internal signaling */
1298 	hdlr_enable(SIGTTIN, hdlr_sigttin_ou);
1299 	hdlr_enable(SIGTTOU, hdlr_sigttin_ou);
1300 
1301 	/* first, parse the command line options. We do not carry out any actual work, just
1302 	 * see what we should do. This relieves us from certain anomalies and we can process
1303 	 * the parameters down below in the correct order. For example, we must know the
1304 	 * value of -M before we can do the init, but at the same time we need to have
1305 	 * the base classes init before we can process most of the options. Now, with the
1306 	 * split of functionality, this is no longer a problem. Thanks to varmofekoj for
1307 	 * suggesting this algo.
1308 	 * Note: where we just need to set some flags and can do so without knowledge
1309 	 * of other options, we do this during the inital option processing.
1310 	 * rgerhards, 2008-04-04
1311 	 */
1312 #if defined(_AIX)
1313 	while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) {
1314 #else
1315 	while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwx")) != EOF) {
1316 #endif
1317 		switch((char)ch) {
1318 		case '4':
1319 		case '6':
1320 		case 'A':
1321 		case 'f': /* configuration file */
1322 		case 'i': /* pid file name */
1323 		case 'n': /* don't fork */
1324 		case 'N': /* enable config verify mode */
1325 		case 'q': /* add hostname if DNS resolving has failed */
1326 		case 'Q': /* dont resolve hostnames in ACL to IPs */
1327 		case 'S': /* Source IP for local client to be used on multihomed host */
1328 		case 'T': /* chroot on startup (primarily for testing) */
1329 		case 'u': /* misc user settings */
1330 		case 'w': /* disable disallowed host warnings */
1331 		case 'C':
1332 		case 'o': /* write output config file */
1333 		case 'x': /* disable dns for remote messages */
1334 			CHKiRet(bufOptAdd(ch, optarg));
1335 			break;
1336 #if defined(_AIX)
1337 		case 'R':  /* This option is a no-op for AIX */
1338 			break;
1339 #endif
1340 		case 'd': /* debug - must be handled now, so that debug is active during init! */
1341 			debugging_on = 1;
1342 			Debug = 1;
1343 			yydebug = 1;
1344 			break;
1345 		case 'D': /* BISON debug */
1346 			yydebug = 1;
1347 			break;
1348 		case 'M': /* default module load path -- this MUST be carried out immediately! */
1349 			glblModPath = (uchar*) optarg;
1350 			break;
1351 		case 'v': /* MUST be carried out immediately! */
1352 			printVersion();
1353 			exit(0); /* exit for -v option - so this is a "good one" */
1354 		case 'h':
1355 		case '?':
1356 		default:
1357 			rsyslogd_usage();
1358 		}
1359 	}
1360 
1361 	if(argc - optind)
1362 		rsyslogd_usage();
1363 
1364 	DBGPRINTF("rsyslogd %s startup, module path '%s', cwd:%s\n",
1365 		  VERSION, glblModPath == NULL ? "" : (char*)glblModPath,
1366 		  getcwd(cwdbuf, sizeof(cwdbuf)));
1367 
1368 	/* we are done with the initial option parsing and processing. Now we init the system. */
1369 
1370 	CHKiRet(rsyslogd_InitGlobalClasses());
1371 
1372 	/* doing some core initializations */
1373 
1374 	if((iRet = modInitIminternal()) != RS_RET_OK) {
1375 		fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
1376 			iRet);
1377 		exit(1); /* "good" exit, leaving at init for fatal error */
1378 	}
1379 
1380 	/* get our host and domain names - we need to do this early as we may emit
1381 	 * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04
1382 	 * But we need to have imInternal up first!
1383 	 */
1384 	queryLocalHostname();
1385 
1386 	/* we now can emit error messages "the regular way" */
1387 
1388 	if(getenv("TZ") == NULL) {
1389 		const char *const tz =
1390 			(access("/etc/localtime", R_OK) == 0) ? "TZ=/etc/localtime" : "TZ=UTC";
1391 		putenv((char*)tz);
1392 		if(emitTZWarning) {
1393 			LogMsg(0, RS_RET_NO_TZ_SET, LOG_WARNING, "environment variable TZ is not "
1394 				"set, auto correcting this to %s", tz);
1395 		} else {
1396 			dbgprintf("environment variable TZ is not set, auto correcting this to %s\n", tz);
1397 		}
1398 	}
1399 
1400 	/* END core initializations - we now come back to carrying out command line options*/
1401 
1402 	while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) {
1403 		DBGPRINTF("deque option %c, optarg '%s'\n", ch, (arg == NULL) ? "" : arg);
1404 		switch((char)ch) {
1405 		case '4':
1406 			fprintf (stderr, "rsyslogd: the -4 command line option will go away "
1407 				 "soon.\nPlease use the global(net.ipprotocol=\"ipv4-only\") "
1408 				 "configuration parameter instead.\n");
1409 	                glbl.SetDefPFFamily(PF_INET);
1410 			break;
1411 		case '6':
1412 			fprintf (stderr, "rsyslogd: the -6 command line option will go away "
1413 				 "soon.\nPlease use the global(net.ipprotocol=\"ipv6-only\") "
1414 				 "configuration parameter instead.\n");
1415 			glbl.SetDefPFFamily(PF_INET6);
1416 			break;
1417 		case 'A':
1418 			fprintf (stderr, "rsyslogd: the -A command line option will go away "
1419 				 "soon.\n"
1420 				 "Please use the omfwd parameter \"upd.sendToAll\" instead.\n");
1421 			send_to_all++;
1422 			break;
1423 		case 'S':		/* Source IP for local client to be used on multihomed host */
1424 			fprintf (stderr, "rsyslogd: the -S command line option will go away "
1425 				 "soon.\n"
1426 				 "Please use the omrelp parameter \"localClientIP\" instead.\n");
1427 			if(glbl.GetSourceIPofLocalClient() != NULL) {
1428 				fprintf (stderr, "rsyslogd: Only one -S argument allowed, the first one is taken.\n");
1429 			} else {
1430 				glbl.SetSourceIPofLocalClient((uchar*)arg);
1431 			}
1432 			break;
1433 		case 'f':		/* configuration file */
1434 			ConfFile = (uchar*) arg;
1435 			break;
1436 		case 'i':		/* pid file name */
1437 			free((void*)PidFile);
1438 			PidFile = arg;
1439 			break;
1440 		case 'n':		/* don't fork */
1441 			doFork = 0;
1442 			break;
1443 		case 'N':		/* enable config verify mode */
1444 			iConfigVerify = (arg == NULL) ? 0 : atoi(arg);
1445 			break;
1446 		case 'o':
1447 			if(fp_rs_full_conf_output != NULL) {
1448 				fprintf(stderr, "warning: -o option given multiple times. Now "
1449 					"using value %s\n", (arg == NULL) ? "-" : arg);
1450 				fclose(fp_rs_full_conf_output);
1451 				fp_rs_full_conf_output = NULL;
1452 			}
1453 			if(arg == NULL || !strcmp(arg, "-")) {
1454 				fp_rs_full_conf_output = stdout;
1455 			} else {
1456 				fp_rs_full_conf_output = fopen(arg, "w");
1457 			}
1458 			if(fp_rs_full_conf_output == NULL) {
1459 				perror(arg);
1460 				fprintf (stderr, "rsyslogd: cannot open config output file %s - "
1461 					"-o option will be ignored\n", arg);
1462 			} else {
1463 				time_t tTime;
1464 				struct tm tp;
1465 				datetime.GetTime(&tTime);
1466 				localtime_r(&tTime, &tp);
1467 				fprintf(fp_rs_full_conf_output,
1468 					"## full conf created by rsyslog version %s at "
1469 					"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d ##\n",
1470 					VERSION, tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday,
1471 					tp.tm_hour, tp.tm_min, tp.tm_sec);
1472 			}
1473 			break;
1474 		case 'q':               /* add hostname if DNS resolving has failed */
1475 			fprintf (stderr, "rsyslogd: the -q command line option will go away "
1476 				 "soon.\nPlease use the global(net.aclAddHostnameOnFail=\"on\") "
1477 				 "configuration parameter instead.\n");
1478 		        *(net.pACLAddHostnameOnFail) = 1;
1479 		        break;
1480 		case 'Q':               /* dont resolve hostnames in ACL to IPs */
1481 			fprintf (stderr, "rsyslogd: the -Q command line option will go away "
1482 				 "soon.\nPlease use the global(net.aclResolveHostname=\"off\") "
1483 				 "configuration parameter instead.\n");
1484 		        *(net.pACLDontResolve) = 1;
1485 		        break;
1486 		case 'T':/* chroot() immediately at program startup, but only for testing, NOT security yet */
1487 			if(arg == NULL) {
1488 				/* note this case should already be handled by getopt,
1489 				 * but we want to keep the static analyzer happy.
1490 				 */
1491 				fprintf(stderr, "-T options needs a parameter\n");
1492 				exit(1);
1493 			}
1494 			if(chroot(arg) != 0) {
1495 				perror("chroot");
1496 				exit(1);
1497 			}
1498 			if(chdir("/") != 0) {
1499 				perror("chdir");
1500 				exit(1);
1501 			}
1502 			break;
1503 		case 'u':		/* misc user settings */
1504 			iHelperUOpt = (arg == NULL) ? 0 : atoi(arg);
1505 			if(iHelperUOpt & 0x01) {
1506 				fprintf (stderr, "rsyslogd: the -u command line option will go away "
1507 					 "soon.\n"
1508 					 "For the 0x01 bit, please use the "
1509 					 "global(parser.parseHostnameAndTag=\"off\") "
1510 					 "configuration parameter instead.\n");
1511 				glbl.SetParseHOSTNAMEandTAG(0);
1512 			}
1513 			if(iHelperUOpt & 0x02) {
1514 				fprintf (stderr, "rsyslogd: the -u command line option will go away "
1515 					 "soon.\n"
1516 					 "For the 0x02 bit, please use the -C option instead.");
1517 				bChDirRoot = 0;
1518 			}
1519 			break;
1520 		case 'C':
1521 			bChDirRoot = 0;
1522 			break;
1523 		case 'w':		/* disable disallowed host warnigs */
1524 			fprintf (stderr, "rsyslogd: the -w command line option will go away "
1525 				 "soon.\nPlease use the global(net.permitWarning=\"off\") "
1526 				 "configuration parameter instead.\n");
1527 			glbl.SetOption_DisallowWarning(0);
1528 			break;
1529 		case 'x':		/* disable dns for remote messages */
1530 			fprintf (stderr, "rsyslogd: the -x command line option will go away "
1531 				 "soon.\nPlease use the global(net.enableDNS=\"off\") "
1532 				 "configuration parameter instead.\n");
1533 			glbl.SetDisableDNS(1);
1534 			break;
1535 		case 'h':
1536 		case '?':
1537 		default:
1538 			rsyslogd_usage();
1539 		}
1540 	}
1541 
1542 	if(iRet != RS_RET_END_OF_LINKEDLIST)
1543 		FINALIZE;
1544 
1545 	if(iConfigVerify) {
1546 		doFork = 0;
1547 		fprintf(stderr, "rsyslogd: version %s, config validation run (level %d), master config %s\n",
1548 			VERSION, iConfigVerify, ConfFile);
1549 	}
1550 
1551 	resetErrMsgsFlag();
1552 	localRet = rsconf.Load(&ourConf, ConfFile);
1553 
1554 	if(fp_rs_full_conf_output != NULL) {
1555 		if(fp_rs_full_conf_output != stdout) {
1556 			fclose(fp_rs_full_conf_output);
1557 		}
1558 		fp_rs_full_conf_output = NULL;
1559 	}
1560 
1561 	/* check for "hard" errors that needs us to abort in any case */
1562 	if(   (localRet == RS_RET_CONF_FILE_NOT_FOUND)
1563 	   || (localRet == RS_RET_NO_ACTIONS) ) {
1564 		/* for extreme testing, we keep the ability to let rsyslog continue
1565 		 * even on hard config errors. Note that this may lead to segfaults
1566 		 * or other malfunction further down the road.
1567 		 */
1568 		if((glblDevOptions & DEV_OPTION_KEEP_RUNNING_ON_HARD_CONF_ERROR) == 1) {
1569 			fprintf(stderr, "rsyslogd: NOTE: developer-only option set to keep rsyslog "
1570 				"running where it should abort - this can lead to "
1571 				"more problems later in the run.\n");
1572 		} else {
1573 			ABORT_FINALIZE(localRet);
1574 		}
1575 	}
1576 
1577 	glbl.GenerateLocalHostNameProperty();
1578 
1579 	if(hadErrMsgs()) {
1580 		if(loadConf->globals.bAbortOnUncleanConfig) {
1581 			fprintf(stderr, "rsyslogd: global(AbortOnUncleanConfig=\"on\") is set, and "
1582 				"config is not clean.\n"
1583 				"Check error log for details, fix errors and restart. As a last\n"
1584 				"resort, you may want to use global(AbortOnUncleanConfig=\"off\") \n"
1585 				"to permit a startup with a dirty config.\n");
1586 			exit(2);
1587 		}
1588 		if(iConfigVerify) {
1589 			/* a bit dirty, but useful... */
1590 			exit(1);
1591 		}
1592 		localRet = RS_RET_OK;
1593 	}
1594 	CHKiRet(localRet);
1595 
1596 	CHKiRet(rsyslogd_InitStdRatelimiters());
1597 
1598 	if(bChDirRoot) {
1599 		if(chdir("/") != 0)
1600 			fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
1601 	}
1602 
1603 	if(iConfigVerify)
1604 		FINALIZE;
1605 	/* after this point, we are in a "real" startup */
1606 
1607 	thrdInit();
1608 	CHKiRet(checkStartupOK());
1609 	if(doFork) {
1610 		parentPipeFD = forkRsyslog();
1611 	}
1612 	glblSetOurPid(getpid());
1613 
1614 	hdlr_enable(SIGPIPE, SIG_IGN);
1615 	hdlr_enable(SIGXFSZ, SIG_IGN);
1616 	if(Debug || glblPermitCtlC) {
1617 		hdlr_enable(SIGUSR1, rsyslogdDebugSwitch);
1618 		hdlr_enable(SIGINT,  rsyslogdDoDie);
1619 		hdlr_enable(SIGQUIT, rsyslogdDoDie);
1620 	} else {
1621 		hdlr_enable(SIGUSR1, SIG_IGN);
1622 		hdlr_enable(SIGINT,  SIG_IGN);
1623 		hdlr_enable(SIGQUIT, SIG_IGN);
1624 	}
1625 	hdlr_enable(SIGTERM, rsyslogdDoDie);
1626 	hdlr_enable(SIGCHLD, hdlr_sigchld);
1627 	hdlr_enable(SIGHUP, hdlr_sighup);
1628 
1629 	if(rsconfNeedDropPriv(ourConf)) {
1630 		/* need to write pid file early as we may loose permissions */
1631 		CHKiRet(writePidFile());
1632 	}
1633 
1634 	CHKiRet(rsconf.Activate(ourConf));
1635 
1636 	if(ourConf->globals.bLogStatusMsgs) {
1637 		char bufStartUpMsg[512];
1638 		snprintf(bufStartUpMsg, sizeof(bufStartUpMsg),
1639 			 "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
1640 			 "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] start",
1641 			 (int) glblGetOurPid());
1642 		logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
1643 	}
1644 
1645 	if(!rsconfNeedDropPriv(ourConf)) {
1646 		CHKiRet(writePidFile());
1647 	}
1648 
1649 	/* END OF INTIALIZATION */
1650 	DBGPRINTF("rsyslogd: initialization completed, transitioning to regular run mode\n");
1651 
1652 	if(doFork) {
1653 		tellChildReady(parentPipeFD, "OK");
1654 		stddbg = -1; /* turn off writing to fd 1 */
1655 		close(1);
1656 		close(2);
1657 		ourConf->globals.bErrMsgToStderr = 0;
1658 	}
1659 
1660 finalize_it:
1661 	if(iRet == RS_RET_VALIDATION_RUN) {
1662 		fprintf(stderr, "rsyslogd: End of config validation run. Bye.\n");
1663 		exit(0);
1664 	} else if(iRet != RS_RET_OK) {
1665 		fprintf(stderr, "rsyslogd: run failed with error %d (see rsyslog.h "
1666 				"or try https://www.rsyslog.com/e/%d to learn what that number means)\n",
1667 				iRet, iRet*-1);
1668 		exit(1);
1669 	}
1670 
1671 }
1672 
1673 
1674 /* this function pulls all internal messages from the buffer
1675  * and puts them into the processing engine.
1676  * We can only do limited error handling, as this would not
1677  * really help us. TODO: add error messages?
1678  * rgerhards, 2007-08-03
1679  */
1680 void
1681 processImInternal(void)
1682 {
1683 	smsg_t *pMsg;
1684 	smsg_t *repMsg;
1685 
1686 	while(iminternalRemoveMsg(&pMsg) == RS_RET_OK) {
1687 		rsRetVal localRet = ratelimitMsg(internalMsg_ratelimiter, pMsg, &repMsg);
1688 		if(repMsg != NULL) {
1689 			logmsgInternal_doWrite(repMsg);
1690 		}
1691 		if(localRet == RS_RET_OK) {
1692 			logmsgInternal_doWrite(pMsg);
1693 		}
1694 	}
1695 }
1696 
1697 
1698 /* This takes a received message that must be decoded and submits it to
1699  * the main message queue. This is a legacy function which is being provided
1700  * to aid older input plugins that do not support message creation via
1701  * the new interfaces themselves. It is not recommended to use this
1702  * function for new plugins. -- rgerhards, 2009-10-12
1703  */
1704 rsRetVal
1705 parseAndSubmitMessage(const uchar *const hname, const uchar *const hnameIP, const uchar *const msg,
1706 	const int len, const int flags, const flowControl_t flowCtlType,
1707 	prop_t *const pInputName,
1708 	const struct syslogTime *const stTime,
1709 	const time_t ttGenTime,
1710 	ruleset_t *const pRuleset)
1711 {
1712 	prop_t *pProp = NULL;
1713 	smsg_t *pMsg = NULL;
1714 	DEFiRet;
1715 
1716 	/* we now create our own message object and submit it to the queue */
1717 	if(stTime == NULL) {
1718 		CHKiRet(msgConstruct(&pMsg));
1719 	} else {
1720 		CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
1721 	}
1722 	if(pInputName != NULL)
1723 		MsgSetInputName(pMsg, pInputName);
1724 	MsgSetRawMsg(pMsg, (char*)msg, len);
1725 	MsgSetFlowControlType(pMsg, flowCtlType);
1726 	MsgSetRuleset(pMsg, pRuleset);
1727 	pMsg->msgFlags  = flags | NEEDS_PARSING;
1728 
1729 	MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &pProp);
1730 	CHKiRet(prop.Destruct(&pProp));
1731 	CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hnameIP), &pProp));
1732 	CHKiRet(prop.Destruct(&pProp));
1733 	CHKiRet(submitMsg2(pMsg));
1734 
1735 finalize_it:
1736 	if(iRet != RS_RET_OK) {
1737 		DBGPRINTF("parseAndSubmitMessage() error, discarding msg: %s\n", msg);
1738 		if(pMsg != NULL) {
1739 			msgDestruct(&pMsg);
1740 		}
1741 	}
1742 	RETiRet;
1743 }
1744 
1745 
1746 /* helper to doHUP(), this "HUPs" each action. The necessary locking
1747  * is done inside the action class and nothing we need to take care of.
1748  * rgerhards, 2008-10-22
1749  */
1750 DEFFUNC_llExecFunc(doHUPActions)
1751 {
1752 	dbgprintf("doHUP called\n");
1753 	actionCallHUPHdlr((action_t*) pData);
1754 	return RS_RET_OK; /* we ignore errors, we can not do anything either way */
1755 }
1756 
1757 
1758 /* This function processes a HUP after one has been detected. Note that this
1759  * is *NOT* the sighup handler. The signal is recorded by the handler, that record
1760  * detected inside the mainloop and then this function is called to do the
1761  * real work. -- rgerhards, 2008-10-22
1762  * Note: there is a VERY slim chance of a data race when the hostname is reset.
1763  * We prefer to take this risk rather than sync all accesses, because to the best
1764  * of my analysis it can not really hurt (the actual property is reference-counted)
1765  * but the sync would require some extra CPU for *each* message processed.
1766  * rgerhards, 2012-04-11
1767  */
1768 static void
1769 doHUP(void)
1770 {
1771 	char buf[512];
1772 
1773 	if(ourConf->globals.bLogStatusMsgs) {
1774 		snprintf(buf, sizeof(buf),
1775 			 "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION
1776 			 "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] rsyslogd was HUPed",
1777 			 (int) glblGetOurPid());
1778 			errno = 0;
1779 		logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
1780 	}
1781 
1782 	queryLocalHostname(); /* re-read our name */
1783 	ruleset.IterateAllActions(ourConf, doHUPActions, NULL);
1784 	modDoHUP();
1785 	lookupDoHUP();
1786 	errmsgDoHUP();
1787 }
1788 
1789 /* rsyslogdDoDie() is a signal handler. If called, it sets the bFinished variable
1790  * to indicate the program should terminate. However, it does not terminate
1791  * it itself, because that causes issues with multi-threading. The actual
1792  * termination is then done on the main thread. This solution might introduce
1793  * a minimal delay, but it is much cleaner than the approach of doing everything
1794  * inside the signal handler.
1795  * rgerhards, 2005-10-26
1796  * Note:
1797  * - we do not call DBGPRINTF() as this may cause us to block in case something
1798  *   with the threading is wrong.
1799  * - we do not really care about the return state of write(), but we need this
1800  *   strange check we do to silence compiler warnings (thanks, Ubuntu!)
1801  */
1802 void
1803 rsyslogdDoDie(int sig)
1804 {
1805 #	define MSG1 "DoDie called.\n"
1806 #	define MSG2 "DoDie called 5 times - unconditional exit\n"
1807 	static int iRetries = 0; /* debug aid */
1808 	dbgprintf(MSG1);
1809 	if(Debug == DEBUG_FULL) {
1810 		if(write(1, MSG1, sizeof(MSG1) - 1) == -1) {
1811 			dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__);
1812 		}
1813 	}
1814 	if(iRetries++ == 4) {
1815 		if(Debug == DEBUG_FULL) {
1816 			if(write(1, MSG2, sizeof(MSG2) - 1) == -1) {
1817 				dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__);
1818 			}
1819 		}
1820 		abort();
1821 	}
1822 	bFinished = sig;
1823 	if(glblDebugOnShutdown) {
1824 		/* kind of hackish - set to 0, so that debug_swith will enable
1825 		 * and AND emit the "start debug log" message.
1826 		 */
1827 		debugging_on = 0;
1828 		rsyslogdDebugSwitch();
1829 	}
1830 #	undef MSG1
1831 #	undef MSG2
1832 	/* at least on FreeBSD we seem not to necessarily awake the main thread.
1833 	 * So let's do it explicitely.
1834 	 */
1835 	dbgprintf("awaking mainthread\n");
1836 	pthread_kill(mainthread, SIGTTIN);
1837 }
1838 
1839 
1840 static void
1841 wait_timeout(const sigset_t *sigmask)
1842 {
1843 	struct timespec tvSelectTimeout;
1844 
1845 	tvSelectTimeout.tv_sec = janitorInterval * 60; /* interval is in minutes! */
1846 	tvSelectTimeout.tv_nsec = 0;
1847 
1848 #ifdef _AIX
1849 	if(!src_exists) {
1850 		/* it looks like select() is NOT interrupted by HUP, even though
1851 		 * SA_RESTART is not given in the signal setup. As this code is
1852 		 * not expected to be used in production (when running as a
1853 		 * service under src control), we simply make a kind of
1854 		 * "somewhat-busy-wait" algorithm. We compute our own
1855 		 * timeout value, which we count down to zero. We do this
1856 		 * in useful subsecond steps.
1857 		 */
1858 		const long wait_period = 500000000; /* wait period in nanoseconds */
1859 		int timeout = janitorInterval * 60 * (1000000000 / wait_period);
1860 
1861 		tvSelectTimeout.tv_sec = 0;
1862 		tvSelectTimeout.tv_nsec = wait_period;
1863 		do {
1864 			if(bFinished || bHadHUP) {
1865 				break;
1866 			}
1867 			pselect(1, NULL, NULL, NULL, &tvSelectTimeout, sigmask);
1868 		} while(--timeout > 0);
1869 	} else {
1870 		char buf[256];
1871 		fd_set rfds;
1872 
1873 		FD_ZERO(&rfds);
1874 		FD_SET(SRC_FD, &rfds);
1875 		if(pselect(SRC_FD + 1, (fd_set *)&rfds, NULL, NULL, &tvSelectTimeout, sigmask))
1876 		{
1877 			if(FD_ISSET(SRC_FD, &rfds))
1878 			{
1879 				rc = recvfrom(SRC_FD, &srcpacket, SRCMSG, 0, &srcaddr, &addrsz);
1880 				if(rc < 0) {
1881 					if (errno != EINTR)
1882 					{
1883 						fprintf(stderr,"%s: ERROR: '%d' recvfrom\n", progname,errno);
1884 						exit(1); //TODO: this needs to be handled gracefully
1885 					} else { /* punt on short read */
1886 						return;
1887 					}
1888 
1889 					switch(srcpacket.subreq.action)
1890 					{
1891 					case START:
1892 						dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support this "
1893 										"option.\n", sizeof(struct srcrep));
1894 						break;
1895 					case STOP:
1896 						if (srcpacket.subreq.object == SUBSYSTEM) {
1897 							dosrcpacket(SRC_OK,NULL,sizeof(struct srcrep));
1898 							(void) snprintf(buf, sizeof(buf) / sizeof(char), " [origin "
1899 								"software=\"rsyslogd\" " "swVersion=\"" VERSION \
1900 								"\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]"
1901 								" exiting due to stopsrc.",
1902 								(int) glblGetOurPid());
1903 							errno = 0;
1904 							logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
1905 							return ;
1906 						} else
1907 							dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support "
1908 									"this option.\n",sizeof(struct srcrep));
1909 						break;
1910 					case REFRESH:
1911 						dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support this "
1912 								"option.\n", sizeof(struct srcrep));
1913 						break;
1914 					default:
1915 						dosrcpacket(SRC_SUBICMD,NULL,sizeof(struct srcrep));
1916 						break;
1917 
1918 					}
1919 				}
1920 			}
1921 		}
1922 	}
1923 #else
1924 	pselect(0, NULL, NULL, NULL, &tvSelectTimeout, sigmask);
1925 #endif /* AIXPORT : SRC end */
1926 }
1927 
1928 
1929 static void
1930 reapChild(void)
1931 {
1932 	pid_t child;
1933 	do {
1934 		int status;
1935 		child = waitpid(-1, &status, WNOHANG);
1936 		if(child != -1 && child != 0) {
1937 			glblReportChildProcessExit(NULL, child, status);
1938 		}
1939 	} while(child > 0);
1940 }
1941 
1942 
1943 /* This is the main processing loop. It is called after successful initialization.
1944  * When it returns, the syslogd terminates.
1945  * Its sole function is to provide some housekeeping things. The real work is done
1946  * by the other threads spawned.
1947  */
1948 static void
1949 mainloop(void)
1950 {
1951 	time_t tTime;
1952 	sigset_t origmask;
1953 	sigset_t sigblockset;
1954 
1955 	sigemptyset(&sigblockset);
1956 	sigaddset(&sigblockset, SIGTERM);
1957 	sigaddset(&sigblockset, SIGCHLD);
1958 	sigaddset(&sigblockset, SIGHUP);
1959 
1960 	do {
1961 		processImInternal();
1962 
1963 		pthread_sigmask(SIG_BLOCK, &sigblockset, &origmask);
1964 		if(bChildDied) {
1965 			reapChild();
1966 			bChildDied = 0;
1967 		}
1968 
1969 		if(bHadHUP) {
1970 			doHUP();
1971 			bHadHUP = 0;
1972 		}
1973 
1974 		if(bFinished)
1975 			break;	/* exit as quickly as possible */
1976 
1977 		wait_timeout(&origmask);
1978 		pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
1979 
1980 		janitorRun();
1981 
1982 		datetime.GetTime(&tTime);
1983 		checkGoneAwaySenders(tTime);
1984 
1985 	} while(!bFinished); /* end do ... while() */
1986 }
1987 
1988 /* Finalize and destruct all actions.
1989  */
1990 static void
1991 rsyslogd_destructAllActions(void)
1992 {
1993 	ruleset.DestructAllActions(runConf);
1994 	PREFER_STORE_0_TO_INT(&bHaveMainQueue); /* flag that internal messages need to be temporarily stored */
1995 }
1996 
1997 
1998 /* de-initialize everything, make ready for termination */
1999 static void
2000 deinitAll(void)
2001 {
2002 	char buf[256];
2003 
2004 	DBGPRINTF("exiting on signal %d\n", bFinished);
2005 
2006 	/* IMPORTANT: we should close the inputs first, and THEN send our termination
2007 	 * message. If we do it the other way around, logmsgInternal() may block on
2008 	 * a full queue and the inputs still fill up that queue. Depending on the
2009 	 * scheduling order, we may end up with logmsgInternal being held for a quite
2010 	 * long time. When the inputs are terminated first, that should not happen
2011 	 * because the queue is drained in parallel. The situation could only become
2012 	 * an issue with extremely long running actions in a queue full environment.
2013 	 * However, such actions are at least considered poorly written, if not
2014 	 * outright wrong. So we do not care about this very remote problem.
2015 	 * rgerhards, 2008-01-11
2016 	 */
2017 
2018 	/* close the inputs */
2019 	DBGPRINTF("Terminating input threads...\n");
2020 	glbl.SetGlobalInputTermination();
2021 
2022 	thrdTerminateAll();
2023 
2024 	/* and THEN send the termination log message (see long comment above) */
2025 	if(bFinished && runConf->globals.bLogStatusMsgs) {
2026 		(void) snprintf(buf, sizeof(buf),
2027 		 "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
2028 		 "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]" " exiting on signal %d.",
2029 		 (int) glblGetOurPid(), bFinished);
2030 		errno = 0;
2031 		logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
2032 	}
2033 	processImInternal(); /* make sure not-yet written internal messages are processed */
2034 	/* we sleep a couple of ms to give the queue a chance to pick up the late messages
2035 	 * (including exit message); otherwise we have seen cases where the message did
2036 	 * not make it to log files, even on idle systems.
2037 	 */
2038 	srSleep(0, 50);
2039 
2040 	/* drain queue (if configured so) and stop main queue worker thread pool */
2041 	DBGPRINTF("Terminating main queue...\n");
2042 	qqueueDestruct(&pMsgQueue);
2043 	pMsgQueue = NULL;
2044 
2045 	/* Free ressources and close connections. This includes flushing any remaining
2046 	 * repeated msgs.
2047 	 */
2048 	DBGPRINTF("Terminating outputs...\n");
2049 	rsyslogd_destructAllActions();
2050 
2051 	DBGPRINTF("all primary multi-thread sources have been terminated - now doing aux cleanup...\n");
2052 
2053 	DBGPRINTF("destructing current config...\n");
2054 	rsconf.Destruct(&runConf);
2055 
2056 	modExitIminternal();
2057 
2058 	if(pInternalInputName != NULL)
2059 		prop.Destruct(&pInternalInputName);
2060 
2061 	/* the following line cleans up CfSysLineHandlers that were not based on loadable
2062 	 * modules. As such, they are not yet cleared.  */
2063 	unregCfSysLineHdlrs();
2064 
2065 	/* this is the last spot where this can be done - below output modules are unloaded! */
2066 
2067 	parserClassExit();
2068 	rsconfClassExit();
2069 	strExit();
2070 	ratelimitModExit();
2071 	dnscacheDeinit();
2072 	thrdExit();
2073 	objRelease(net, LM_NET_FILENAME);
2074 
2075 	module.UnloadAndDestructAll(eMOD_LINK_ALL);
2076 
2077 	rsrtExit(); /* runtime MUST always be deinitialized LAST (except for debug system) */
2078 	DBGPRINTF("Clean shutdown completed, bye\n");
2079 
2080 	errmsgExit();
2081 	/* dbgClassExit MUST be the last one, because it de-inits the debug system */
2082 	dbgClassExit();
2083 
2084 	/* NO CODE HERE - dbgClassExit() must be the last thing before exit()! */
2085 	if(strcmp(PidFile, NO_PIDFILE)) {
2086 		unlink(PidFile);
2087 	}
2088 }
2089 
2090 /* This is the main entry point into rsyslogd. This must be a function in its own
2091  * right in order to intialize the debug system in a portable way (otherwise we would
2092  * need to have a statement before variable definitions.
2093  * rgerhards, 20080-01-28
2094  */
2095 int
2096 main(int argc, char **argv)
2097 {
2098 #if defined(_AIX)
2099 	/* SRC support : fd 0 (stdin) must be the SRC socket
2100 	 * startup.  fd 0 is duped to a new descriptor so that stdin can be used
2101 	 * internally by rsyslogd.
2102 	 */
2103 
2104 	strncpy(progname,argv[0], sizeof(progname)-1);
2105 	addrsz = sizeof(srcaddr);
2106 	if ((rc = getsockname(0, &srcaddr, &addrsz)) < 0) {
2107 		fprintf(stderr, "%s: continuing without SRC support\n", progname);
2108 		src_exists = FALSE;
2109 	}
2110 	if (src_exists)
2111 		if(dup2(0, SRC_FD) == -1) {
2112 			fprintf(stderr, "%s: dup2 failed exiting now...\n", progname);
2113 			/* In the unlikely event of dup2 failing we exit */
2114 			exit(-1);
2115 		}
2116 #endif
2117 
2118 	mainthread = pthread_self();
2119 	if((int) getpid() == 1) {
2120 		fprintf(stderr, "rsyslogd %s: running as pid 1, enabling "
2121 			"container-specific defaults, press ctl-c to "
2122 			"terminate rsyslog\n", VERSION);
2123 		PidFile = strdup("NONE"); /* disables pid file writing */
2124 		glblPermitCtlC = 1;
2125 		runningInContainer = 1;
2126 		emitTZWarning = 1;
2127 	} else {
2128 		/* "dynamic defaults" - non-container case */
2129 		PidFile = strdup(PATH_PIDFILE);
2130 	}
2131 	if(PidFile == NULL) {
2132 		fprintf(stderr, "rsyslogd: could not alloc memory for pid file "
2133 			"default name - aborting\n");
2134 		exit(1);
2135 	}
2136 
2137 	/* disable case-sensitive comparisons in variable subsystem: */
2138 	fjson_global_do_case_sensitive_comparison(0);
2139 
2140 	const char *const log_dflt = getenv("RSYSLOG_DFLT_LOG_INTERNAL");
2141 	if(log_dflt != NULL && !strcmp(log_dflt, "1"))
2142 		bProcessInternalMessages = 1;
2143 	dbgClassInit();
2144 	initAll(argc, argv);
2145 #ifdef HAVE_LIBSYSTEMD
2146 	sd_notify(0, "READY=1");
2147 	dbgprintf("done signaling to systemd that we are ready!\n");
2148 #endif
2149 	DBGPRINTF("max message size: %d\n", glblGetMaxLine());
2150 	DBGPRINTF("----RSYSLOGD INITIALIZED\n");
2151 	LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd fully started up and initialized "
2152 		"- begin actual processing");
2153 
2154 	mainloop();
2155 	LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd shutting down");
2156 	deinitAll();
2157 #ifdef ENABLE_LIBLOGGING_STDLOG
2158 	stdlog_close(stdlog_hdl);
2159 #endif
2160 	osf_close();
2161 	return 0;
2162 }
2163