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