~ubuntu-branches/ubuntu/karmic/rsyslog/karmic-200908151517

« back to all changes in this revision

Viewing changes to syslogd.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2008-04-23 16:46:39 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080423164639-5acmt8a4vpxjgnxw
Tags: 3.14.2-3
* debian/rsyslog-doc.install
  - Fix a typo in the install path of the dia files. Closes: #477489
    Thanks to Justin B Rye for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *
8
8
 * to learn more about it and discuss any questions you may have.
9
9
 *
10
 
 * Please note that as of now, a lot of the code in this file stems
11
 
 * from the sysklogd project. To learn more over this project, please
12
 
 * visit
13
 
 *
14
 
 * http://www.infodrom.org/projects/sysklogd/
15
 
 *
 
10
 * rsyslog had initially been forked from the sysklogd project.
16
11
 * I would like to express my thanks to the developers of the sysklogd
17
12
 * package - without it, I would have had a much harder start...
18
13
 *
19
 
 * Please note that I made quite some changes to the orignal package.
20
 
 * I expect to do even more changes - up
21
 
 * to a full rewrite - to meet my design goals, which among others
22
 
 * contain a (at least) dual-thread design with a memory buffer for
23
 
 * storing received bursts of data. This is also the reason why I 
24
 
 * kind of "forked" a completely new branch of the package. My intension
25
 
 * is to do many changes and only this initial release will look
26
 
 * similar to sysklogd (well, one never knows...).
27
 
 *
28
 
 * As I have made a lot of modifications, please assume that all bugs
29
 
 * in this package are mine and not those of the sysklogd team.
30
 
 *
31
 
 * As of this writing, there already exist heavy
32
 
 * modifications to the orginal sysklogd package. I suggest to no
33
 
 * longer rely too much on code knowledge you eventually have with
34
 
 * sysklogd - rgerhards 2005-07-05
35
 
 * The code is now almost completely different. Be careful!
36
 
 * rgerhards, 2006-11-30
37
 
 * 
38
 
 * I have decided to put my code under the GPL. The sysklog package
39
 
 * is distributed under the BSD license. As such, this package here
40
 
 * currently comes with two licenses. Both are given below. As it is
41
 
 * probably hard for you to see what was part of the sysklogd package
42
 
 * and what is part of my code, I suggest that you visit the 
43
 
 * sysklogd site on the URL above if you would like to base your
44
 
 * development on a version that is not under the GPL.
 
14
 * Please note that while rsyslog started from the sysklogd code base,
 
15
 * it nowadays has almost nothing left in common with it. Allmost all
 
16
 * parts of the code have been rewritten.
45
17
 *
46
18
 * This Project was intiated and is maintained by
47
19
 * Rainer Gerhards <rgerhards@hq.adiscon.com>. See
64
36
 *       to the database).
65
37
 *
66
38
 * rsyslog - An Enhanced syslogd Replacement.
67
 
 * Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
68
 
 *
69
 
 * This program is free software; you can redistribute it and/or
70
 
 * modify it under the terms of the GNU General Public License
71
 
 * as published by the Free Software Foundation; either version 2
72
 
 * of the License, or (at your option) any later version.
73
 
 *
74
 
 * This program is distributed in the hope that it will be useful,
 
39
 * Copyright 2003-2008 Rainer Gerhards and Adiscon GmbH.
 
40
 *
 
41
 * This file is part of rsyslog.
 
42
 *
 
43
 * Rsyslog is free software: you can redistribute it and/or modify
 
44
 * it under the terms of the GNU General Public License as published by
 
45
 * the Free Software Foundation, either version 3 of the License, or
 
46
 * (at your option) any later version.
 
47
 *
 
48
 * Rsyslog is distributed in the hope that it will be useful,
75
49
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
76
50
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
77
51
 * GNU General Public License for more details.
78
52
 *
79
53
 * You should have received a copy of the GNU General Public License
80
 
 * along with this program; if not, write to the Free Software
81
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
54
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
82
55
 *
83
56
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
84
57
 */
85
58
#include "config.h"
86
59
#include "rsyslog.h"
87
60
 
88
 
#ifdef __FreeBSD__
89
 
#define BSD
90
 
#endif
91
 
 
92
61
/* change the following setting to e.g. 32768 if you would like to
93
62
 * support large message sizes for IHE (32k is the current maximum
94
63
 * needed for IHE). I was initially tempted to increase it to 32k,
116
85
 * I have increased the default message size to 2048 to be in sync
117
86
 * with recent IETF syslog standardization efforts.
118
87
 * rgerhards, 2006-11-30
119
 
 *
120
 
 * I have removed syslogdPanic(). That function was supposed to be used
121
 
 * for logging in low-memory conditons. Ever since it was introduced, it
122
 
 * was a wrapper for dbgprintf(). A more intelligent choice was hard to
123
 
 * find. After all, if we are short on memory, doing anything fance will
124
 
 * again cause memory problems. I have now modified the code so that
125
 
 * those elements for which we do not get memory are simply discarded.
126
 
 * That might be a single property like the TAG, but it might also be
127
 
 * a complete message. The overall goal of this code change is to keep
128
 
 * rsyslogd up and running, while we sacrifice some messages to reach
129
 
 * that goal. It also keeps the code cleaner. A real out of memory
130
 
 * condition is highly unlikely. If it happens, there will probably be
131
 
 * much more trouble on the system in question. Anyhow - rsyslogd will
132
 
 * most probably be able to survive it and carry on with processing
133
 
 * once the situation has been resolved.
134
88
 */
135
89
#define DEFUPRI         (LOG_USER|LOG_NOTICE)
136
 
#define DEFSPRI         (LOG_KERN|LOG_CRIT)
137
90
#define TIMERINTVL      30              /* interval for checking flush, mark */
138
91
 
139
 
#define CONT_LINE       1               /* Allow continuation lines */
140
 
 
141
 
#ifdef MTRACE
142
 
#include <mcheck.h>
143
 
#endif
144
92
#include <unistd.h>
145
93
#include <stdlib.h>
146
94
#include <stdio.h>
147
95
#include <stddef.h>
148
96
#include <ctype.h>
 
97
#include <limits.h>
149
98
#define GNU_SOURCE
150
99
#include <string.h>
151
100
#include <stdarg.h>
152
101
#include <time.h>
153
 
#include <dlfcn.h>
 
102
#include <assert.h>
 
103
#include <libgen.h>
154
104
 
155
 
#include <sys/syslog.h>
156
 
#include <sys/param.h>
157
105
#ifdef  __sun
158
 
#include <errno.h>
 
106
#       include <errno.h>
159
107
#else
160
 
#include <sys/errno.h>
 
108
#       include <sys/errno.h>
161
109
#endif
162
110
#include <sys/ioctl.h>
163
111
#include <sys/wait.h>
164
 
#include <sys/socket.h>
165
112
#include <sys/file.h>
166
 
#include <sys/un.h>
167
 
#include <sys/time.h>
168
 
#ifdef BSD
 
113
 
 
114
#if HAVE_SYS_TIMESPEC_H
169
115
# include <sys/timespec.h>
170
116
#endif
171
 
#include <sys/resource.h>
 
117
 
 
118
#if HAVE_SYS_STAT_H
 
119
#       include <sys/stat.h>
 
120
#endif
 
121
 
172
122
#include <signal.h>
173
123
 
174
 
#include <netinet/in.h>
175
 
#include <netdb.h>
176
 
#include <fnmatch.h>
177
 
#include <dirent.h>
178
 
 
179
 
#ifndef __sun
180
 
#endif
181
 
#include <arpa/nameser.h>
182
 
#include <arpa/inet.h>
183
 
#include <resolv.h>
 
124
#if HAVE_PATHS_H
 
125
#include <paths.h>
 
126
#endif
 
127
 
 
128
#ifdef USE_NETZIP
 
129
#include <zlib.h>
 
130
#endif
 
131
 
184
132
#include "pidfile.h"
185
 
 
186
 
#include <assert.h>
187
 
 
188
 
#ifdef USE_PTHREADS
189
 
#include <pthread.h>
190
 
#endif
191
 
 
192
 
#if     HAVE_PATHS_H
193
 
#include <paths.h>
194
 
#endif
195
 
 
196
 
 
197
 
/* handle some defines missing on more than one platform */
198
 
#ifndef SUN_LEN
199
 
#define SUN_LEN(su) \
200
 
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
201
 
#endif
202
 
 
203
133
#include "srUtils.h"
204
134
#include "stringbuf.h"
205
135
#include "syslogd-types.h"
206
136
#include "template.h"
207
137
#include "outchannel.h"
208
138
#include "syslogd.h"
209
 
#include "net.h" /* struct NetAddr */
210
139
 
211
 
#include "parse.h"
212
140
#include "msg.h"
213
141
#include "modules.h"
214
142
#include "action.h"
220
148
#include "omfwd.h"
221
149
#include "omfile.h"
222
150
#include "omdiscard.h"
 
151
#include "threads.h"
 
152
#include "queue.h"
 
153
#include "stream.h"
 
154
#include "wti.h"
 
155
#include "wtp.h"
 
156
#include "expr.h"
 
157
#include "ctok.h"
 
158
#include "conf.h"
 
159
#include "vmop.h"
 
160
#include "vmstk.h"
 
161
#include "vm.h"
 
162
#include "vmprg.h"
 
163
#include "errmsg.h"
 
164
#include "datetime.h"
 
165
#include "sysvar.h"
 
166
 
 
167
/* definitions for objects we access */
 
168
DEFobjCurrIf(obj)
 
169
DEFobjCurrIf(datetime)
 
170
DEFobjCurrIf(conf)
 
171
DEFobjCurrIf(expr)
 
172
DEFobjCurrIf(vm)
 
173
DEFobjCurrIf(var)
 
174
DEFobjCurrIf(module)
 
175
DEFobjCurrIf(errmsg)
 
176
DEFobjCurrIf(net) /* TODO: make go away! */
 
177
 
 
178
 
 
179
/* forward definitions */
 
180
static rsRetVal GlobalClassExit(void);
223
181
 
224
182
/* We define our own set of syslog defintions so that we
225
183
 * do not need to rely on (possibly different) implementations.
231
189
#ifdef __sun
232
190
#       define LOG_AUTHPRIV LOG_AUTH
233
191
#endif
234
 
#define LOG_MAKEPRI(fac, pri)   (((fac) << 3) | (pri))
235
 
#define LOG_PRI(p)      ((p) & LOG_PRIMASK)
236
 
#define LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
237
192
#define INTERNAL_NOPRI  0x10    /* the "no priority" priority */
238
193
#define LOG_FTP         (11<<3) /* ftp daemon */
239
 
#define INTERNAL_MARK   LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
240
 
 
241
 
syslogCODE rs_prioritynames[] =
242
 
  {
243
 
    { "alert", LOG_ALERT },
244
 
    { "crit", LOG_CRIT },
245
 
    { "debug", LOG_DEBUG },
246
 
    { "emerg", LOG_EMERG },
247
 
    { "err", LOG_ERR },
248
 
    { "error", LOG_ERR },               /* DEPRECATED */
249
 
    { "info", LOG_INFO },
250
 
    { "none", INTERNAL_NOPRI },         /* INTERNAL */
251
 
    { "notice", LOG_NOTICE },
252
 
    { "panic", LOG_EMERG },             /* DEPRECATED */
253
 
    { "warn", LOG_WARNING },            /* DEPRECATED */
254
 
    { "warning", LOG_WARNING },
255
 
    { NULL, -1 }
256
 
  };
257
 
 
258
 
syslogCODE rs_facilitynames[] =
259
 
  {
260
 
    { "auth", LOG_AUTH },
261
 
    { "authpriv", LOG_AUTHPRIV },
262
 
    { "cron", LOG_CRON },
263
 
    { "daemon", LOG_DAEMON },
264
 
    { "ftp", LOG_FTP },
265
 
    { "kern", LOG_KERN },
266
 
    { "lpr", LOG_LPR },
267
 
    { "mail", LOG_MAIL },
268
 
    { "mark", INTERNAL_MARK },          /* INTERNAL */
269
 
    { "news", LOG_NEWS },
270
 
    { "security", LOG_AUTH },           /* DEPRECATED */
271
 
    { "syslog", LOG_SYSLOG },
272
 
    { "user", LOG_USER },
273
 
    { "uucp", LOG_UUCP },
274
 
    { "local0", LOG_LOCAL0 },
275
 
    { "local1", LOG_LOCAL1 },
276
 
    { "local2", LOG_LOCAL2 },
277
 
    { "local3", LOG_LOCAL3 },
278
 
    { "local4", LOG_LOCAL4 },
279
 
    { "local5", LOG_LOCAL5 },
280
 
    { "local6", LOG_LOCAL6 },
281
 
    { "local7", LOG_LOCAL7 },
282
 
    { NULL, -1 }
283
 
  };
284
194
 
285
195
 
286
196
#ifndef UTMP_FILE
304
214
#endif
305
215
 
306
216
#if defined(SYSLOGD_PIDNAME)
307
 
#undef _PATH_LOGPID
308
 
#if defined(FSSTND)
309
 
#ifdef BSD
310
 
#define _PATH_VARRUN "/var/run/"
311
 
#endif
312
 
#ifdef __sun
313
 
#define _PATH_VARRUN "/var/run/"
314
 
#endif
315
 
#define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
316
 
#else
317
 
#define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
318
 
#endif
319
 
#else
320
 
#ifndef _PATH_LOGPID
321
 
#if defined(FSSTND)
322
 
#define _PATH_LOGPID _PATH_VARRUN "rsyslogd.pid"
323
 
#else
324
 
#define _PATH_LOGPID "/etc/rsyslogd.pid"
325
 
#endif
326
 
#endif
 
217
#       undef _PATH_LOGPID
 
218
#       if defined(FSSTND)
 
219
#               ifdef BSD
 
220
#                       define _PATH_VARRUN "/var/run/"
 
221
#               endif
 
222
#               if defined(__sun) || defined(__hpux)
 
223
#                       define _PATH_VARRUN "/var/run/"
 
224
#               endif
 
225
#               define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
 
226
#       else
 
227
#               define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
 
228
#       endif
 
229
#else
 
230
#       ifndef _PATH_LOGPID
 
231
#               if defined(__sun) || defined(__hpux)
 
232
#                       define _PATH_VARRUN "/var/run/"
 
233
#               endif
 
234
#               if defined(FSSTND)
 
235
#                       define _PATH_LOGPID _PATH_VARRUN "rsyslogd.pid"
 
236
#               else
 
237
#                       define _PATH_LOGPID "/etc/rsyslogd.pid"
 
238
#               endif
 
239
#       endif
327
240
#endif
328
241
 
329
242
#ifndef _PATH_DEV
330
 
#define _PATH_DEV       "/dev/"
 
243
#       define _PATH_DEV        "/dev/"
331
244
#endif
332
245
 
333
246
#ifndef _PATH_CONSOLE
338
251
#define _PATH_TTY       "/dev/tty"
339
252
#endif
340
253
 
341
 
#ifndef _PATH_LOG
342
 
#ifdef BSD
343
 
#define _PATH_LOG       "/var/run/log"
344
 
#else
345
 
#define _PATH_LOG       "/dev/log"
346
 
#endif
347
 
#endif
348
 
 
349
 
 
350
 
/* IPv6 compatibility layer for older platforms
351
 
 * We need to handle a few things different if we are running
352
 
 * on an older platform which does not support all the glory
353
 
 * of IPv6. We try to limit toll on features and reliability,
354
 
 * but obviously it is better to run rsyslog on a platform that
355
 
 * supports everything...
356
 
 * rgerhards, 2007-06-22
357
 
 */
358
 
#ifndef AI_NUMERICSERV
359
 
#  define AI_NUMERICSERV 0
360
 
#endif
361
 
 
362
 
 
363
254
static uchar    *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
364
255
static char     *PidFile = _PATH_LOGPID; /* read-only after startup */
365
 
static uchar    *pModDir = NULL; /* read-only after startup */
366
 
char    ctty[] = _PATH_CONSOLE; /* this is read-only */
 
256
char    ctty[] = _PATH_CONSOLE; /* this is read-only; used by omfile -- TODO: remove that dependency */
367
257
 
368
258
static pid_t myPid;     /* our pid for use in self-generated messages, e.g. on startup */
369
259
/* mypid is read-only after the initial fork() */
370
 
static int debugging_on = 0; /* read-only, except on sig USR1 */
371
260
static int restart = 0; /* do restart (config read) - multithread safe */
372
261
 
373
 
static int bRequestDoMark = 0; /* do mark processing? (multithread safe) */
374
 
#define MAXFUNIX        20
375
 
 
376
262
int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */
377
 
int startIndexUxLocalSockets = 0; /* process funix from that index on (used to 
378
 
                                   * suppress local logging. rgerhards 2005-08-01
379
 
                                   * read-only after startup
380
 
                                   */
381
 
int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name?  read-only after startup */
382
 
char *funixn[MAXFUNIX] = { _PATH_LOG }; /* read-only after startup */
383
 
int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
384
 
 
385
 
#define INTERNAL_NOPRI  0x10    /* the "no priority" priority */
386
 
#define TABLE_NOPRI     0       /* Value to indicate no priority in f_pmask */
387
 
#define TABLE_ALLPRI    0xFF    /* Value to indicate all priorities in f_pmask */
388
 
#define LOG_MARK        LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */
389
 
 
390
 
/* definitions used for doNameLine to differentiate between different command types
391
 
 * (with otherwise identical code). This is a left-over from the previous config
392
 
 * system. It stays, because it is still useful. So do not wonder why it looks
393
 
 * somewhat strange (at least its name). -- rgerhards, 2007-08-01
394
 
 */
395
 
enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2};
396
 
 
397
 
/* The following global variables are used for building
398
 
 * tag and host selector lines during startup and config reload.
399
 
 * This is stored as a global variable pool because of its ease. It is
400
 
 * also fairly compatible with multi-threading as the stratup code must
401
 
 * be run in a single thread anyways. So there can be no race conditions. These
402
 
 * variables are no longer used once the configuration has been loaded (except,
403
 
 * of course, during a reload). rgerhards 2005-10-18
404
 
 */
405
 
static EHostnameCmpMode eDfltHostnameCmpMode;
406
 
static rsCStrObj *pDfltHostnameCmp;
407
 
static rsCStrObj *pDfltProgNameCmp;
408
 
 
409
 
/* supporting structures for multithreading */
410
 
#ifdef USE_PTHREADS
411
 
/* this is the first approach to a queue, this time with static
412
 
 * memory.
413
 
 */
414
 
typedef struct {
415
 
        void** pbuf;
416
 
        long head, tail;
417
 
        int full, empty;
418
 
        pthread_mutex_t *mut;
419
 
        pthread_cond_t *notFull, *notEmpty;
420
 
} msgQueue;
421
 
 
422
 
int iMainMsgQueueSize;
423
 
int bRunningMultithreaded = 0;  /* Is this program running in multithreaded mode? */
424
 
msgQueue *pMsgQueue = NULL;
425
 
static pthread_t thrdWorker;
426
 
static int bGlblDone = 0;
427
 
#endif
428
 
/* END supporting structures for multithreading */
 
263
 
429
264
 
430
265
static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
431
266
                                      * parsed inside message - rgerhards, 2006-03-13 */
434
269
                                 * termination.
435
270
                                 */
436
271
 
437
 
/*
438
 
 * Intervals at which we flush out "message repeated" messages,
 
272
/* Intervals at which we flush out "message repeated" messages,
439
273
 * in seconds after previous message is logged.  After each flush,
440
274
 * we move to the next interval until we reach the largest.
 
275
 * TODO: this shall go into action object! -- rgerhards, 2008-01-29
441
276
 */
442
 
int     repeatinterval[] = { 30, 60 };  /* # of secs before flush */
443
 
#define MAXREPEAT ((int)((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1))
444
 
#define REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
445
 
#define BACKOFF(f)      { if (++(f)->f_repeatcount > MAXREPEAT) \
446
 
                                 (f)->f_repeatcount = MAXREPEAT; \
447
 
                        }
448
 
#ifdef SYSLOG_INET
449
 
union sockunion {
450
 
        struct sockinet {
451
 
                u_char si_len;
452
 
                u_char si_family;
453
 
                } su_si;
454
 
        struct sockaddr_in  su_sin;
455
 
        struct sockaddr_in6 su_sin6;
456
 
};
457
 
#endif
 
277
int     repeatinterval[2] = { 30, 60 }; /* # of secs before flush */
458
278
 
459
279
#define LIST_DELIMITER  ':'             /* delimiter between two hosts */
460
280
 
461
281
struct  filed *Files = NULL; /* read-only after init() (but beware of sigusr1!) */
462
282
 
463
 
struct code {
464
 
        char    *c_name;
465
 
        int     c_val;
466
 
};
467
 
 
468
 
static struct code      PriNames[] = {
469
 
        {"alert",       LOG_ALERT},
470
 
        {"crit",        LOG_CRIT},
471
 
        {"debug",       LOG_DEBUG},
472
 
        {"emerg",       LOG_EMERG},
473
 
        {"err",         LOG_ERR},
474
 
        {"error",       LOG_ERR},               /* DEPRECATED */
475
 
        {"info",        LOG_INFO},
476
 
        {"none",        INTERNAL_NOPRI},        /* INTERNAL */
477
 
        {"notice",      LOG_NOTICE},
478
 
        {"panic",       LOG_EMERG},             /* DEPRECATED */
479
 
        {"warn",        LOG_WARNING},           /* DEPRECATED */
480
 
        {"warning",     LOG_WARNING},
481
 
        {"*",           TABLE_ALLPRI},
482
 
        {NULL,          -1}
483
 
};
484
 
 
485
 
static struct code      FacNames[] = {
486
 
        {"auth",         LOG_AUTH},
487
 
        {"authpriv",     LOG_AUTHPRIV},
488
 
        {"cron",         LOG_CRON},
489
 
        {"daemon",       LOG_DAEMON},
490
 
        {"kern",         LOG_KERN},
491
 
        {"lpr",          LOG_LPR},
492
 
        {"mail",         LOG_MAIL},
493
 
        {"mark",         LOG_MARK},             /* INTERNAL */
494
 
        {"news",         LOG_NEWS},
495
 
        {"security",     LOG_AUTH},             /* DEPRECATED */
496
 
        {"syslog",       LOG_SYSLOG},
497
 
        {"user",         LOG_USER},
498
 
        {"uucp",         LOG_UUCP},
499
 
#if defined(LOG_FTP)
500
 
        {"ftp",          LOG_FTP},
501
 
#endif
502
 
        {"local0",       LOG_LOCAL0},
503
 
        {"local1",       LOG_LOCAL1},
504
 
        {"local2",       LOG_LOCAL2},
505
 
        {"local3",       LOG_LOCAL3},
506
 
        {"local4",       LOG_LOCAL4},
507
 
        {"local5",       LOG_LOCAL5},
508
 
        {"local6",       LOG_LOCAL6},
509
 
        {"local7",       LOG_LOCAL7},
510
 
        {NULL,           -1},
511
 
};
512
 
 
513
283
static pid_t ppid; /* This is a quick and dirty hack used for spliting main/startup thread */
514
284
 
 
285
typedef struct legacyOptsLL_s {
 
286
        uchar *line;
 
287
        struct legacyOptsLL_s *next;
 
288
} legacyOptsLL_t;
 
289
legacyOptsLL_t *pLegacyOptsLL = NULL;
 
290
 
515
291
/* global variables for config file state */
516
292
static int      bDropTrailingLF = 1; /* drop trailing LF's on reception? */
517
 
int     Debug;          /* debug flag  - read-only after startup */
 
293
int     iCompatibilityMode = 0;         /* version we should be compatible with; 0 means sysklogd. It is
 
294
                                           the default, so if no -c<n> option is given, we make ourselvs
 
295
                                           as compatible to sysklogd as possible. */
518
296
static int      bDebugPrintTemplateList = 1;/* output template list in debug mode? */
519
297
static int      bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
520
298
static int      bDebugPrintModuleList = 1;/* output module list in debug mode? */
521
299
int     bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
522
300
static uchar    cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
523
 
static int      bEscapeCCOnRcv; /* escape control characters on reception: 0 - no, 1 - yes */
524
 
static int      bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
525
 
static int      bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
526
 
static int      logEveryMsg = 0;/* no repeat message processing  - read-only after startup
527
 
                                 * 0 - suppress duplicate messages
528
 
                                 * 1 - do NOT suppress duplicate messages
529
 
                                 */
 
301
static int      bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
 
302
int     bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
 
303
int     bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
 
304
uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */
530
305
/* end global config file state variables */
531
306
 
532
 
static unsigned int Forwarding = 0;
533
 
static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
534
307
char    LocalHostName[MAXHOSTNAMELEN+1];/* our hostname  - read-only after startup */
535
308
char    *LocalDomain;   /* our local domain name  - read-only after startup */
536
 
int     *finet = NULL;  /* Internet datagram sockets, first element is nbr of elements
537
 
                                 * read-only after init(), but beware of restart! */
538
 
static char     *LogPort = "514";    /* port number for INET connections */
539
 
static int      MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
 
309
int     MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
540
310
int      family = PF_UNSPEC;     /* protocol family (IPv4, IPv6 or both), set via cmdline */
541
311
int      send_to_all = 0;        /* send message to all IPv4/IPv6 addresses */
542
 
static int      MarkSeq = 0;    /* mark sequence number - modified in domark() only */
543
312
static int      NoFork = 0;     /* don't fork - don't run in daemon mode - read-only after startup */
544
 
static int      AcceptRemote = 0;/* receive messages that come via UDP - read-only after startup */
545
313
int     DisableDNS = 0; /* don't look up IP addresses of remote messages */
546
314
char    **StripDomains = NULL;/* these domains may be stripped before writing logs  - r/o after s.u., never touched by init */
547
315
char    **LocalHosts = NULL;/* these hosts are logged with their hostname  - read-only after startup, never touched by init */
548
 
int     NoHops = 1;     /* Can we bounce syslog messages through an
549
 
                                   intermediate host.  Read-only after startup */
550
 
static int     Initialized = 0; /* set when we have initialized ourselves
551
 
                                 * rgerhards 2004-11-09: and by initialized, we mean that
552
 
                                 * the configuration file could be properly read AND the
553
 
                                 * syslog/udp port could be obtained (the later is debatable).
554
 
                                 * It is mainly a setting used for emergency logging: if
555
 
                                 * something really goes wild, we can not do as indicated in
556
 
                                 * the log file, but we still log messages to the system
557
 
                                 * console. This is probably the best that can be done in
558
 
                                 * such a case.
559
 
                                 * read-only after startup, but modified during restart
560
 
                                 */
 
316
static int      bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
 
317
                                 * If the main queue is either not yet ready or not running in 
 
318
                                 * queueing mode (mode DIRECT!), then this is set to 0.
 
319
                                 */
561
320
 
562
321
extern  int errno;
563
322
 
564
 
 
565
 
/* This structure represents the files that will have log
566
 
 * copies printed.
567
 
 * RGerhards 2004-11-08: Each instance of the filed structure 
568
 
 * describes what I call an "output channel". This is important
569
 
 * to mention as we now allow database connections to be
570
 
 * present in the filed structure. If helps immensely, if we
571
 
 * think of it as the abstraction of an output channel.
572
 
 * rgerhards, 2005-10-26: The structure below provides ample
573
 
 * opportunity for non-thread-safety. Each of the variable
574
 
 * accesses must be carefully evaluated, many of them probably
575
 
 * be guarded by mutexes. But beware of deadlocks...
576
 
 * rgerhards, 2007-08-01: as you can see, the structure has shrunk pretty much. I will
577
 
 * remove some of the comments some time. It's still the structure that controls much
578
 
 * of the processing that goes on in syslogd, but it now has lots of helpers.
579
 
 */
580
 
struct filed {
581
 
        struct  filed *f_next;          /* next in linked list */
582
 
        /* filter properties */
583
 
        enum {
584
 
                FILTER_PRI = 0,         /* traditional PRI based filer */
585
 
                FILTER_PROP = 1         /* extended filter, property based */
586
 
        } f_filter_type;
587
 
        EHostnameCmpMode eHostnameCmpMode;
588
 
        rsCStrObj *pCSHostnameComp;     /* hostname to check */
589
 
        rsCStrObj *pCSProgNameComp;     /* tag to check or NULL, if not to be checked */
590
 
        union {
591
 
                u_char  f_pmask[LOG_NFACILITIES+1];     /* priority mask */
592
 
                struct {
593
 
                        rsCStrObj *pCSPropName;
594
 
                        enum {
595
 
                                FIOP_NOP = 0,           /* do not use - No Operation */
596
 
                                FIOP_CONTAINS  = 1,     /* contains string? */
597
 
                                FIOP_ISEQUAL  = 2,      /* is (exactly) equal? */
598
 
                                FIOP_STARTSWITH = 3,    /* starts with a string? */
599
 
                                FIOP_REGEX = 4          /* matches a regular expression? */
600
 
                        } operation;
601
 
                        rsCStrObj *pCSCompValue;        /* value to "compare" against */
602
 
                        char isNegated;                 /* actually a boolean ;) */
603
 
                } prop;
604
 
        } f_filterData;
605
 
 
606
 
        linkedList_t llActList; /* list of configured actions */
607
 
};
608
 
typedef struct filed selector_t;        /* new type name */
 
323
/* main message queue and its configuration parameters */
 
324
static queue_t *pMsgQueue = NULL;                               /* the main message queue */
 
325
static int iMainMsgQueueSize = 10000;                           /* size of the main message queue above */
 
326
static int iMainMsgQHighWtrMark = 8000;                         /* high water mark for disk-assisted queues */
 
327
static int iMainMsgQLowWtrMark = 2000;                          /* low water mark for disk-assisted queues */
 
328
static int iMainMsgQDiscardMark = 9800;                         /* begin to discard messages */
 
329
static int iMainMsgQDiscardSeverity = 8;                        /* by default, discard nothing to prevent unintentional loss */
 
330
static int iMainMsgQueueNumWorkers = 1;                         /* number of worker threads for the mm queue above */
 
331
static queueType_t MainMsgQueType = QUEUETYPE_FIXED_ARRAY;      /* type of the main message queue above */
 
332
static uchar *pszMainMsgQFName = NULL;                          /* prefix for the main message queue file */
 
333
static int64 iMainMsgQueMaxFileSize = 1024*1024;
 
334
static int iMainMsgQPersistUpdCnt = 0;                          /* persist queue info every n updates */
 
335
static int iMainMsgQtoQShutdown = 0;                            /* queue shutdown */ 
 
336
static int iMainMsgQtoActShutdown = 1000;                       /* action shutdown (in phase 2) */ 
 
337
static int iMainMsgQtoEnq = 2000;                               /* timeout for queue enque */ 
 
338
static int iMainMsgQtoWrkShutdown = 60000;                      /* timeout for worker thread shutdown */
 
339
static int iMainMsgQWrkMinMsgs = 100;                           /* minimum messages per worker needed to start a new one */
 
340
static int iMainMsgQDeqSlowdown = 0;                            /* dequeue slowdown (simple rate limiting) */
 
341
static int bMainMsgQSaveOnShutdown = 1;                         /* save queue on shutdown (when DA enabled)? */
 
342
static int64 iMainMsgQueMaxDiskSpace = 0;                       /* max disk space allocated 0 ==> unlimited */
609
343
 
610
344
 
611
345
/* support for simple textual representation of FIOP names
646
380
        bDebugPrintCfSysLineHandlerList = 1;
647
381
        bDebugPrintModuleList = 1;
648
382
        bEscapeCCOnRcv = 1; /* default is to escape control characters */
649
 
        bReduceRepeatMsgs = (logEveryMsg == 1) ? 0 : 1;
 
383
        bReduceRepeatMsgs = 0;
650
384
        bDropMalPTRMsgs = 0;
651
 
        if(pModDir != NULL) {
652
 
                free(pModDir);
653
 
                pModDir = NULL;
654
 
        }
655
 
#ifdef USE_PTHREADS
 
385
        if(pszWorkDir != NULL) {
 
386
                free(pszWorkDir);
 
387
                pszWorkDir = NULL;
 
388
        }
 
389
        if(pszMainMsgQFName != NULL) {
 
390
                free(pszMainMsgQFName);
 
391
                pszMainMsgQFName = NULL;
 
392
        }
656
393
        iMainMsgQueueSize = 10000;
657
 
#endif
 
394
        iMainMsgQHighWtrMark = 8000;
 
395
        iMainMsgQLowWtrMark = 2000;
 
396
        iMainMsgQDiscardMark = 9800;
 
397
        iMainMsgQDiscardSeverity = 4;
 
398
        iMainMsgQueMaxFileSize = 1024 * 1024;
 
399
        iMainMsgQueueNumWorkers = 1;
 
400
        iMainMsgQPersistUpdCnt = 0;
 
401
        iMainMsgQtoQShutdown = 0;
 
402
        iMainMsgQtoActShutdown = 1000;
 
403
        iMainMsgQtoEnq = 2000;
 
404
        iMainMsgQtoWrkShutdown = 60000;
 
405
        iMainMsgQWrkMinMsgs = 100;
 
406
        iMainMsgQDeqSlowdown = 0;
 
407
        bMainMsgQSaveOnShutdown = 1;
 
408
        MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
 
409
        iMainMsgQueMaxDiskSpace = 0;
 
410
        glbliActionResumeRetryCount = 0;
658
411
 
659
412
        return RS_RET_OK;
660
413
}
661
414
 
662
415
 
663
 
/* support for defining allowed TCP and UDP senders. We use the same
664
 
 * structure to implement this (a linked list), but we define two different
665
 
 * list roots, one for UDP and one for TCP.
666
 
 * rgerhards, 2005-09-26
667
 
 */
668
 
#ifdef SYSLOG_INET
669
 
/* All of the five below are read-only after startup */
670
 
static struct AllowedSenders *pAllowedSenders_UDP = NULL; /* the roots of the allowed sender */
671
 
struct AllowedSenders *pAllowedSenders_TCP = NULL; /* lists. If NULL, all senders are ok! */
672
 
static struct AllowedSenders *pLastAllowedSenders_UDP = NULL; /* and now the pointers to the last */
673
 
static struct AllowedSenders *pLastAllowedSenders_TCP = NULL; /* element in the respective list */
674
 
#endif /* #ifdef SYSLOG_INET */
675
416
 
676
417
int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
677
418
 
678
419
 
679
420
/* hardcoded standard templates (used for defaults) */
680
 
static uchar template_TraditionalFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
 
421
static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
 
422
static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
 
423
static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
681
424
static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
682
 
static uchar template_StdFwdFmt[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%\"";
 
425
static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg%\"";
 
426
static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg%\"";
683
427
static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
684
428
static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
 
429
static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
685
430
/* end template */
686
431
 
687
432
 
688
433
/* up to the next comment, prototypes that should be removed by reordering */
689
 
#ifdef USE_PTHREADS
690
 
static msgQueue *queueInit (void);
691
 
static void *singleWorker(); /* REMOVEME later 2005-10-24 */
692
 
#endif
693
434
/* Function prototypes. */
694
435
static char **crunch_list(char *list);
695
 
static void printline(char *hname, char *msg, int iSource);
696
 
static void logmsg(int pri, msg_t*, int flags);
697
 
static rsRetVal fprintlog(action_t *pAction);
698
436
static void reapchild();
699
437
static void debug_switch();
700
 
static rsRetVal cfline(uchar *line, selector_t **pfCurr);
701
 
static int decode(uchar *name, struct code *codetab);
702
438
static void sighup_handler();
703
 
static void die(int sig);
704
439
static void freeSelectors(void);
705
 
static rsRetVal processConfFile(uchar *pConfFile);
706
 
static rsRetVal selectorAddList(selector_t *f);
707
440
static void processImInternal(void);
708
441
 
709
 
/* Code for handling allowed/disallowed senders
710
 
 */
711
 
#ifdef SYSLOG_INET
712
 
static inline void MaskIP6 (struct in6_addr *addr, uint8_t bits) {
713
 
        register uint8_t i;
714
 
        
715
 
        assert (addr != NULL);
716
 
        assert (bits <= 128);
717
 
        
718
 
        i = bits/32;
719
 
        if (bits%32)
720
 
                addr->s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
721
 
        for (; i < (sizeof addr->s6_addr32)/4; i++)
722
 
                addr->s6_addr32[i] = 0;
723
 
}
724
 
 
725
 
static inline void MaskIP4 (struct in_addr  *addr, uint8_t bits) {
726
 
        
727
 
        assert (addr != NULL);
728
 
        assert (bits <=32 );
729
 
        
730
 
        addr->s_addr &= htonl(0xffffffff << (32 - bits));
731
 
}
732
 
 
733
 
#define SIN(sa)  ((struct sockaddr_in  *)(sa))
734
 
#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
735
 
 
736
 
/* This function adds an allowed sender entry to the ACL linked list.
737
 
 * In any case, a single entry is added. If an error occurs, the
738
 
 * function does its error reporting itself. All validity checks
739
 
 * must already have been done by the caller.
740
 
 * This is a helper to AddAllowedSender().
741
 
 * rgerhards, 2007-07-17
742
 
 */
743
 
static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
744
 
                                      struct NetAddr *iAllow, uint8_t iSignificantBits)
745
 
{
746
 
        struct AllowedSenders *pEntry = NULL;
747
 
 
748
 
        assert(ppRoot != NULL);
749
 
        assert(ppLast != NULL);
750
 
        assert(iAllow != NULL);
751
 
 
752
 
        if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders))) == NULL) {
753
 
                glblHadMemShortage = 1;
754
 
                return RS_RET_OUT_OF_MEMORY; /* no options left :( */
755
 
        }
756
 
        
757
 
        memcpy(&(pEntry->allowedSender), iAllow, sizeof (struct NetAddr));
758
 
        pEntry->pNext = NULL;
759
 
        pEntry->SignificantBits = iSignificantBits;
760
 
        
761
 
        /* enqueue */
762
 
        if(*ppRoot == NULL) {
763
 
                *ppRoot = pEntry;
764
 
        } else {
765
 
                (*ppLast)->pNext = pEntry;
766
 
        }
767
 
        *ppLast = pEntry;
768
 
        
769
 
        return RS_RET_OK;
770
 
}
771
 
 
772
 
/* function to clear the allowed sender structure in cases where
773
 
 * it must be freed (occurs most often when HUPed.
774
 
 * TODO: reconsider recursive implementation
775
 
 */
776
 
static void clearAllowedSenders (struct AllowedSenders *pAllow) {
777
 
        if (pAllow != NULL) {
778
 
                if (pAllow->pNext != NULL)
779
 
                        clearAllowedSenders (pAllow->pNext);
780
 
                else {
781
 
                        if (F_ISSET(pAllow->allowedSender.flags, ADDR_NAME))
782
 
                                free (pAllow->allowedSender.addr.HostWildcard);
783
 
                        else
784
 
                                free (pAllow->allowedSender.addr.NetAddr);
785
 
                        
786
 
                        free (pAllow);
787
 
                }
788
 
        }
789
 
}
790
 
 
791
 
/* function to add an allowed sender to the allowed sender list. The
792
 
 * root of the list is caller-provided, so it can be used for all
793
 
 * supported lists. The caller must provide a pointer to the root,
794
 
 * as it eventually needs to be updated. Also, a pointer to the
795
 
 * pointer to the last element must be provided (to speed up adding
796
 
 * list elements).
797
 
 * rgerhards, 2005-09-26
798
 
 * If a hostname is given there are possible multiple entries
799
 
 * added (all addresses from that host).
800
 
 */
801
 
static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
802
 
                                 struct NetAddr *iAllow, uint8_t iSignificantBits)
803
 
{
804
 
        DEFiRet;
805
 
 
806
 
        assert(ppRoot != NULL);
807
 
        assert(ppLast != NULL);
808
 
        assert(iAllow != NULL);
809
 
 
810
 
        if (!F_ISSET(iAllow->flags, ADDR_NAME)) {
811
 
                if(iSignificantBits == 0)
812
 
                        /* we handle this seperatly just to provide a better
813
 
                         * error message.
814
 
                         */
815
 
                        logerror("You can not specify 0 bits of the netmask, this would "
816
 
                                 "match ALL systems. If you really intend to do that, "
817
 
                                 "remove all $AllowedSender directives.");
818
 
                
819
 
                switch (iAllow->addr.NetAddr->sa_family) {
820
 
                case AF_INET:
821
 
                        if((iSignificantBits < 1) || (iSignificantBits > 32)) {
822
 
                                logerrorInt("Invalid bit number in IPv4 address - adjusted to 32",
823
 
                                            (int)iSignificantBits);
824
 
                                iSignificantBits = 32;
825
 
                        }
826
 
                        
827
 
                        MaskIP4 (&(SIN(iAllow->addr.NetAddr)->sin_addr), iSignificantBits);
828
 
                        break;
829
 
                case AF_INET6:
830
 
                        if((iSignificantBits < 1) || (iSignificantBits > 128)) {
831
 
                                logerrorInt("Invalid bit number in IPv6 address - adjusted to 128",
832
 
                                            iSignificantBits);
833
 
                                iSignificantBits = 128;
834
 
                        }
835
 
 
836
 
                        MaskIP6 (&(SIN6(iAllow->addr.NetAddr)->sin6_addr), iSignificantBits);
837
 
                        break;
838
 
                default:
839
 
                        /* rgerhards, 2007-07-16: We have an internal program error in this
840
 
                         * case. However, there is not much we can do against it right now. Of
841
 
                         * course, we could abort, but that would probably cause more harm
842
 
                         * than good. So we continue to run. We simply do not add this line - the
843
 
                         * worst thing that happens is that one host will not be allowed to
844
 
                         * log.
845
 
                         */
846
 
                        logerrorInt("Internal error caused AllowedSender to be ignored, AF = %d",
847
 
                                    iAllow->addr.NetAddr->sa_family);
848
 
                        return RS_RET_ERR;
849
 
                }
850
 
                /* OK, entry constructed, now lets add it to the ACL list */
851
 
                iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
852
 
        } else {
853
 
                /* we need to process a hostname ACL */
854
 
                if (DisableDNS) {
855
 
                        logerror ("Ignoring hostname based ACLs because DNS is disabled.");
856
 
                        return RS_RET_OK;
857
 
                }
858
 
                
859
 
                if (!strchr (iAllow->addr.HostWildcard, '*') &&
860
 
                    !strchr (iAllow->addr.HostWildcard, '?')) {
861
 
                        /* single host - in this case, we pull its IP addresses from DNS
862
 
                        * and add IP-based ACLs.
863
 
                        */
864
 
                        struct addrinfo hints, *res, *restmp;
865
 
                        struct NetAddr allowIP;
866
 
                        
867
 
                        memset (&hints, 0, sizeof (struct addrinfo));
868
 
                        hints.ai_family = AF_UNSPEC;
869
 
                        hints.ai_flags  = AI_ADDRCONFIG;
870
 
                        hints.ai_socktype = SOCK_DGRAM;
871
 
 
872
 
                        if (getaddrinfo (iAllow->addr.HostWildcard, NULL, &hints, &res) != 0) {
873
 
                                logerrorSz("DNS error: Can't resolve \"%s\", not added as allowed sender", iAllow->addr.HostWildcard);
874
 
                                /* We could use the text name in this case - maybe this could become
875
 
                                 * a user-defined option at some stage.
876
 
                                 */
877
 
                                return RS_RET_ERR;
878
 
                        }
879
 
                        
880
 
                        for (restmp = res ; res != NULL ; res = res->ai_next) {
881
 
                                switch (res->ai_family) {
882
 
                                case AF_INET: /* add IPv4 */
883
 
                                        iSignificantBits = 32;
884
 
                                        allowIP.flags = 0;
885
 
                                        if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
886
 
                                                glblHadMemShortage = 1;
887
 
                                                return RS_RET_OUT_OF_MEMORY;
888
 
                                        }
889
 
                                        memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
890
 
                                        
891
 
                                        if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits))
892
 
                                                != RS_RET_OK)
893
 
                                                return(iRet);
894
 
                                        break;
895
 
                                case AF_INET6: /* IPv6 - but need to check if it is a v6-mapped IPv4 */
896
 
                                        if(IN6_IS_ADDR_V4MAPPED (&SIN6(res->ai_addr)->sin6_addr)) {
897
 
                                                /* extract & add IPv4 */
898
 
                                                
899
 
                                                iSignificantBits = 32;
900
 
                                                allowIP.flags = 0;
901
 
                                                if((allowIP.addr.NetAddr = malloc(sizeof(struct sockaddr_in)))
902
 
                                                    == NULL) {
903
 
                                                        glblHadMemShortage = 1;
904
 
                                                        return RS_RET_OUT_OF_MEMORY;
905
 
                                                }
906
 
                                                SIN(allowIP.addr.NetAddr)->sin_family = AF_INET;
907
 
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN    
908
 
                                                SIN(allowIP.addr.NetAddr)->sin_len    = sizeof (struct sockaddr_in);
909
 
#endif
910
 
                                                SIN(allowIP.addr.NetAddr)->sin_port   = 0;
911
 
                                                memcpy(&(SIN(allowIP.addr.NetAddr)->sin_addr.s_addr),
912
 
                                                        &(SIN6(res->ai_addr)->sin6_addr.s6_addr32[3]),
913
 
                                                        sizeof (struct sockaddr_in));
914
 
 
915
 
                                                if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
916
 
                                                                iSignificantBits))
917
 
                                                        != RS_RET_OK)
918
 
                                                        return(iRet);
919
 
                                        } else {
920
 
                                                /* finally add IPv6 */
921
 
                                                
922
 
                                                iSignificantBits = 128;
923
 
                                                allowIP.flags = 0;
924
 
                                                if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
925
 
                                                        glblHadMemShortage = 1;
926
 
                                                        return RS_RET_OUT_OF_MEMORY;
927
 
                                                }
928
 
                                                memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
929
 
                                                
930
 
                                                if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
931
 
                                                                iSignificantBits))
932
 
                                                        != RS_RET_OK)
933
 
                                                        return(iRet);
934
 
                                        }
935
 
                                        break;
936
 
                                }
937
 
                        }
938
 
                        freeaddrinfo (restmp);
939
 
                } else {
940
 
                        /* wildcards in hostname - we need to add a text-based ACL.
941
 
                         * For this, we already have everything ready and just need
942
 
                         * to pass it along...
943
 
                         */
944
 
                        iRet =  AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
945
 
                }
946
 
        }
947
 
 
948
 
        return iRet;
949
 
}
950
 
#endif /* #ifdef SYSLOG_INET */
951
 
 
952
 
 
953
 
#ifdef SYSLOG_INET
954
 
/* Print an allowed sender list. The caller must tell us which one.
955
 
 * iListToPrint = 1 means UDP, 2 means TCP
956
 
 * rgerhards, 2005-09-27
957
 
 */
958
 
static void PrintAllowedSenders(int iListToPrint)
959
 
{
960
 
        struct AllowedSenders *pSender;
961
 
        uchar szIP[64];
962
 
        
963
 
        assert((iListToPrint == 1) || (iListToPrint == 2));
964
 
 
965
 
        printf("\nAllowed %s Senders:\n",
966
 
               (iListToPrint == 1) ? "UDP" : "TCP");
967
 
        pSender = (iListToPrint == 1) ?
968
 
                  pAllowedSenders_UDP : pAllowedSenders_TCP;
969
 
        if(pSender == NULL) {
970
 
                printf("\tNo restrictions set.\n");
971
 
        } else {
972
 
                while(pSender != NULL) {
973
 
                        if (F_ISSET(pSender->allowedSender.flags, ADDR_NAME))
974
 
                                printf ("\t%s\n", pSender->allowedSender.addr.HostWildcard);
975
 
                        else {
976
 
                                if(getnameinfo (pSender->allowedSender.addr.NetAddr,
977
 
                                                     SALEN(pSender->allowedSender.addr.NetAddr),
978
 
                                                     (char*)szIP, 64, NULL, 0, NI_NUMERICHOST) == 0) {
979
 
                                        printf ("\t%s/%u\n", szIP, pSender->SignificantBits);
980
 
                                } else {
981
 
                                        /* getnameinfo() failed - but as this is only a
982
 
                                         * debug function, we simply spit out an error and do
983
 
                                         * not care much about it.
984
 
                                         */
985
 
                                        dbgprintf("\tERROR in getnameinfo() - something may be wrong "
986
 
                                                "- ignored for now\n");
987
 
                                }
988
 
                        }
989
 
                        pSender = pSender->pNext;
990
 
                }
991
 
        }
992
 
}
993
 
 
994
 
 
995
 
/* compares a host to an allowed sender list entry. Handles all subleties
996
 
 * including IPv4/v6 as well as domain name wildcards.
997
 
 * This is a helper to isAllowedSender. As it is only called once, it is
998
 
 * declared inline.
999
 
 * Returns 0 if they do not match, something else otherwise.
1000
 
 * contributed 1007-07-16 by mildew@gmail.com
1001
 
 */
1002
 
static inline int MaskCmp(struct NetAddr *pAllow, uint8_t bits, struct sockaddr *pFrom, const char *pszFromHost)
1003
 
{
1004
 
        assert(pAllow != NULL);
1005
 
        assert(pFrom != NULL);
1006
 
 
1007
 
        if(F_ISSET(pAllow->flags, ADDR_NAME)) {
1008
 
                dbgprintf("MaskCmp: host=\"%s\"; pattern=\"%s\"\n", pszFromHost, pAllow->addr.HostWildcard);
1009
 
                
1010
 
                return(fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE|FNM_CASEFOLD) == 0);
1011
 
        } else {/* We need to compare an IP address */
1012
 
                switch (pFrom->sa_family) {
1013
 
                case AF_INET:
1014
 
                        if (AF_INET == pAllow->addr.NetAddr->sa_family)
1015
 
                                return(( SIN(pFrom)->sin_addr.s_addr & htonl(0xffffffff << (32 - bits)) )
1016
 
                                       == SIN(pAllow->addr.NetAddr)->sin_addr.s_addr);
1017
 
                        else
1018
 
                                return 0;
1019
 
                        break;
1020
 
                case AF_INET6:
1021
 
                        switch (pAllow->addr.NetAddr->sa_family) {
1022
 
                        case AF_INET6: {
1023
 
                                struct in6_addr ip, net;
1024
 
                                register uint8_t i;
1025
 
                                
1026
 
                                memcpy (&ip,  &(SIN6(pFrom))->sin6_addr, sizeof (struct in6_addr));
1027
 
                                memcpy (&net, &(SIN6(pAllow->addr.NetAddr))->sin6_addr, sizeof (struct in6_addr));
1028
 
                                
1029
 
                                i = bits/32;
1030
 
                                if (bits % 32)
1031
 
                                        ip.s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
1032
 
                                for (; i < (sizeof ip.s6_addr32)/4; i++)
1033
 
                                        ip.s6_addr32[i] = 0;
1034
 
                                
1035
 
                                return (memcmp (ip.s6_addr, net.s6_addr, sizeof ip.s6_addr) == 0 &&
1036
 
                                        (SIN6(pAllow->addr.NetAddr)->sin6_scope_id != 0 ?
1037
 
                                         SIN6(pFrom)->sin6_scope_id == SIN6(pAllow->addr.NetAddr)->sin6_scope_id : 1));
1038
 
                        }
1039
 
                        case AF_INET: {
1040
 
                                struct in6_addr *ip6 = &(SIN6(pFrom))->sin6_addr;
1041
 
                                struct in_addr  *net = &(SIN(pAllow->addr.NetAddr))->sin_addr;
1042
 
                                
1043
 
                                if ((ip6->s6_addr32[3] & (u_int32_t) htonl((0xffffffff << (32 - bits)))) == net->s_addr &&
1044
 
#if BYTE_ORDER == LITTLE_ENDIAN
1045
 
                                    (ip6->s6_addr32[2] == (u_int32_t)0xffff0000) &&
1046
 
#else
1047
 
                                    (ip6->s6_addr32[2] == (u_int32_t)0x0000ffff) &&
1048
 
#endif
1049
 
                                    (ip6->s6_addr32[1] == 0) && (ip6->s6_addr32[0] == 0))
1050
 
                                        return 1;
1051
 
                                else
1052
 
                                        return 0;
1053
 
                        }
1054
 
                        default:
1055
 
                                /* Unsupported AF */
1056
 
                                return 0;
1057
 
                        }
1058
 
                default:
1059
 
                        /* Unsupported AF */
1060
 
                        return 0;
1061
 
                }
1062
 
        }
1063
 
}
1064
 
 
1065
 
 
1066
 
/* check if a sender is allowed. The root of the the allowed sender.
1067
 
 * list must be proveded by the caller. As such, this function can be
1068
 
 * used to check both UDP and TCP allowed sender lists.
1069
 
 * returns 1, if the sender is allowed, 0 otherwise.
1070
 
 * rgerhards, 2005-09-26
1071
 
 */
1072
 
int isAllowedSender(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost)
1073
 
{
1074
 
        struct AllowedSenders *pAllow;
1075
 
        
1076
 
        assert(pFrom != NULL);
1077
 
 
1078
 
        if(pAllowRoot == NULL)
1079
 
                return 1; /* checking disabled, everything is valid! */
1080
 
        
1081
 
        /* now we loop through the list of allowed senders. As soon as
1082
 
         * we find a match, we return back (indicating allowed). We loop
1083
 
         * until we are out of allowed senders. If so, we fall through the
1084
 
         * loop and the function's terminal return statement will indicate
1085
 
         * that the sender is disallowed.
1086
 
         */
1087
 
        for(pAllow = pAllowRoot ; pAllow != NULL ; pAllow = pAllow->pNext) {
1088
 
                if (MaskCmp (&(pAllow->allowedSender), pAllow->SignificantBits, pFrom, pszFromHost))
1089
 
                        return 1;
1090
 
        }
1091
 
        dbgprintf("%s is not an allowed sender\n", pszFromHost);
1092
 
        return 0;
1093
 
}
1094
 
#endif /* #ifdef SYSLOG_INET */
1095
 
 
1096
 
 
1097
 
/* code to free all sockets within a socket table.
1098
 
 * A socket table is a descriptor table where the zero
1099
 
 * element has the count of elements. This is used for
1100
 
 * listening sockets. The socket table itself is also
1101
 
 * freed.
1102
 
 * A POINTER to this structure must be provided, thus
1103
 
 * double indirection!
1104
 
 * rgerhards, 2007-06-28
1105
 
 */
1106
 
void freeAllSockets(int **socks)
1107
 
{
1108
 
        assert(socks != NULL);
1109
 
        assert(*socks != NULL);
1110
 
        while(**socks) {
1111
 
                dbgprintf("Closing socket %d.\n", (*socks)[**socks]);
1112
 
                close((*socks)[**socks]);
1113
 
                (**socks)--;
1114
 
        }
1115
 
        free(*socks);
1116
 
        socks = NULL;
1117
 
}
1118
 
 
1119
 
 
1120
 
 
1121
 
 
1122
 
/*******************************************************************
1123
 
 * BEGIN CODE-LIBLOGGING                                           *
1124
 
 *******************************************************************
1125
 
 * Code in this section is borrowed from liblogging. This is an
1126
 
 * interim solution. Once liblogging is fully integrated, this is
1127
 
 * to be removed (see http://www.monitorware.com/liblogging for
1128
 
 * more details. 2004-11-16 rgerhards
1129
 
 *
1130
 
 * Please note that the orginal liblogging code is modified so that
1131
 
 * it fits into the context of the current version of syslogd.c.
1132
 
 *
1133
 
 * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!!
1134
 
 */
1135
 
 
1136
 
/**
1137
 
 * Parse a 32 bit integer number from a string.
1138
 
 *
1139
 
 * \param ppsz Pointer to the Pointer to the string being parsed. It
1140
 
 *             must be positioned at the first digit. Will be updated 
1141
 
 *             so that on return it points to the first character AFTER
1142
 
 *             the integer parsed.
1143
 
 * \retval The number parsed.
1144
 
 */
1145
 
 
1146
 
static int srSLMGParseInt32(char** ppsz)
1147
 
{
1148
 
        int i;
1149
 
 
1150
 
        i = 0;
1151
 
        while(isdigit((int) **ppsz))
1152
 
        {
1153
 
                i = i * 10 + **ppsz - '0';
1154
 
                ++(*ppsz);
1155
 
        }
1156
 
 
1157
 
        return i;
1158
 
}
1159
 
 
1160
 
 
1161
 
/**
1162
 
 * Parse a TIMESTAMP-3339.
1163
 
 * updates the parse pointer position.
1164
 
 */
1165
 
static int srSLMGParseTIMESTAMP3339(struct syslogTime *pTime, char** ppszTS)
1166
 
{
1167
 
        char *pszTS = *ppszTS;
1168
 
 
1169
 
        assert(pTime != NULL);
1170
 
        assert(ppszTS != NULL);
1171
 
        assert(pszTS != NULL);
1172
 
 
1173
 
        pTime->year = srSLMGParseInt32(&pszTS);
1174
 
 
1175
 
        /* We take the liberty to accept slightly malformed timestamps e.g. in 
1176
 
         * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course,
1177
 
         * with the current state of affairs, we would never run into this code
1178
 
         * here because at postion 11, there is no "T" in such cases ;)
1179
 
         */
1180
 
        if(*pszTS++ != '-')
1181
 
                return FALSE;
1182
 
        pTime->month = srSLMGParseInt32(&pszTS);
1183
 
        if(pTime->month < 1 || pTime->month > 12)
1184
 
                return FALSE;
1185
 
 
1186
 
        if(*pszTS++ != '-')
1187
 
                return FALSE;
1188
 
        pTime->day = srSLMGParseInt32(&pszTS);
1189
 
        if(pTime->day < 1 || pTime->day > 31)
1190
 
                return FALSE;
1191
 
 
1192
 
        if(*pszTS++ != 'T')
1193
 
                return FALSE;
1194
 
 
1195
 
        pTime->hour = srSLMGParseInt32(&pszTS);
1196
 
        if(pTime->hour < 0 || pTime->hour > 23)
1197
 
                return FALSE;
1198
 
 
1199
 
        if(*pszTS++ != ':')
1200
 
                return FALSE;
1201
 
        pTime->minute = srSLMGParseInt32(&pszTS);
1202
 
        if(pTime->minute < 0 || pTime->minute > 59)
1203
 
                return FALSE;
1204
 
 
1205
 
        if(*pszTS++ != ':')
1206
 
                return FALSE;
1207
 
        pTime->second = srSLMGParseInt32(&pszTS);
1208
 
        if(pTime->second < 0 || pTime->second > 60)
1209
 
                return FALSE;
1210
 
 
1211
 
        /* Now let's see if we have secfrac */
1212
 
        if(*pszTS == '.')
1213
 
        {
1214
 
                char *pszStart = ++pszTS;
1215
 
                pTime->secfrac = srSLMGParseInt32(&pszTS);
1216
 
                pTime->secfracPrecision = (int) (pszTS - pszStart);
1217
 
        }
1218
 
        else
1219
 
        {
1220
 
                pTime->secfracPrecision = 0;
1221
 
                pTime->secfrac = 0;
1222
 
        }
1223
 
 
1224
 
        /* check the timezone */
1225
 
        if(*pszTS == 'Z')
1226
 
        {
1227
 
                pszTS++; /* eat Z */
1228
 
                pTime->OffsetMode = 'Z';
1229
 
                pTime->OffsetHour = 0;
1230
 
                pTime->OffsetMinute = 0;
1231
 
        }
1232
 
        else if((*pszTS == '+') || (*pszTS == '-'))
1233
 
        {
1234
 
                pTime->OffsetMode = *pszTS;
1235
 
                pszTS++;
1236
 
 
1237
 
                pTime->OffsetHour = srSLMGParseInt32(&pszTS);
1238
 
                if(pTime->OffsetHour < 0 || pTime->OffsetHour > 23)
1239
 
                        return FALSE;
1240
 
 
1241
 
                if(*pszTS++ != ':')
1242
 
                        return FALSE;
1243
 
                pTime->OffsetMinute = srSLMGParseInt32(&pszTS);
1244
 
                if(pTime->OffsetMinute < 0 || pTime->OffsetMinute > 59)
1245
 
                        return FALSE;
1246
 
        }
1247
 
        else
1248
 
                /* there MUST be TZ information */
1249
 
                return FALSE;
1250
 
 
1251
 
        /* OK, we actually have a 3339 timestamp, so let's indicated this */
1252
 
        if(*pszTS == ' ')
1253
 
                ++pszTS;
1254
 
        else
1255
 
                return FALSE;
1256
 
 
1257
 
        /* update parse pointer */
1258
 
        *ppszTS = pszTS;
1259
 
 
1260
 
        return TRUE;
1261
 
}
1262
 
 
1263
 
 
1264
 
/**
1265
 
 * Parse a TIMESTAMP-3164.
1266
 
 * Returns TRUE on parse OK, FALSE on parse error.
1267
 
 */
1268
 
static int srSLMGParseTIMESTAMP3164(struct syslogTime *pTime, char* pszTS)
1269
 
{
1270
 
        assert(pTime != NULL);
1271
 
        assert(pszTS != NULL);
1272
 
 
1273
 
        getCurrTime(pTime);     /* obtain the current year and UTC offsets! */
1274
 
 
1275
 
        /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec),
1276
 
         * we may see the following character sequences occur:
1277
 
         *
1278
 
         * J(an/u(n/l)), Feb, Ma(r/y), A(pr/ug), Sep, Oct, Nov, Dec
1279
 
         *
1280
 
         * We will use this for parsing, as it probably is the
1281
 
         * fastest way to parse it.
1282
 
         *
1283
 
         * 2005-07-18, well sometimes it pays to be a bit more verbose, even in C...
1284
 
         * Fixed a bug that lead to invalid detection of the data. The issue was that
1285
 
         * we had an if(++pszTS == 'x') inside of some of the consturcts below. However,
1286
 
         * there were also some elseifs (doing the same ++), which than obviously did not
1287
 
         * check the orginal character but the next one. Now removed the ++ and put it
1288
 
         * into the statements below. Was a really nasty bug... I didn't detect it before
1289
 
         * june, when it first manifested. This also lead to invalid parsing of the rest
1290
 
         * of the message, as the time stamp was not detected to be correct. - rgerhards
1291
 
         */
1292
 
        switch(*pszTS++)
1293
 
        {
1294
 
        case 'J':
1295
 
                if(*pszTS == 'a') {
1296
 
                        ++pszTS;
1297
 
                        if(*pszTS == 'n') {
1298
 
                                ++pszTS;
1299
 
                                pTime->month = 1;
1300
 
                        } else
1301
 
                                return FALSE;
1302
 
                } else if(*pszTS == 'u') {
1303
 
                        ++pszTS;
1304
 
                        if(*pszTS == 'n') {
1305
 
                                ++pszTS;
1306
 
                                pTime->month = 6;
1307
 
                        } else if(*pszTS == 'l') {
1308
 
                                ++pszTS;
1309
 
                                pTime->month = 7;
1310
 
                        } else
1311
 
                                return FALSE;
1312
 
                } else
1313
 
                        return FALSE;
1314
 
                break;
1315
 
        case 'F':
1316
 
                if(*pszTS == 'e') {
1317
 
                        ++pszTS;
1318
 
                        if(*pszTS == 'b') {
1319
 
                                ++pszTS;
1320
 
                                pTime->month = 2;
1321
 
                        } else
1322
 
                                return FALSE;
1323
 
                } else
1324
 
                        return FALSE;
1325
 
                break;
1326
 
        case 'M':
1327
 
                if(*pszTS == 'a') {
1328
 
                        ++pszTS;
1329
 
                        if(*pszTS == 'r') {
1330
 
                                ++pszTS;
1331
 
                                pTime->month = 3;
1332
 
                        } else if(*pszTS == 'y') {
1333
 
                                ++pszTS;
1334
 
                                pTime->month = 5;
1335
 
                        } else
1336
 
                                return FALSE;
1337
 
                } else
1338
 
                        return FALSE;
1339
 
                break;
1340
 
        case 'A':
1341
 
                if(*pszTS == 'p') {
1342
 
                        ++pszTS;
1343
 
                        if(*pszTS == 'r') {
1344
 
                                ++pszTS;
1345
 
                                pTime->month = 4;
1346
 
                        } else
1347
 
                                return FALSE;
1348
 
                } else if(*pszTS == 'u') {
1349
 
                        ++pszTS;
1350
 
                        if(*pszTS == 'g') {
1351
 
                                ++pszTS;
1352
 
                                pTime->month = 8;
1353
 
                        } else
1354
 
                                return FALSE;
1355
 
                } else
1356
 
                        return FALSE;
1357
 
                break;
1358
 
        case 'S':
1359
 
                if(*pszTS == 'e') {
1360
 
                        ++pszTS;
1361
 
                        if(*pszTS == 'p') {
1362
 
                                ++pszTS;
1363
 
                                pTime->month = 9;
1364
 
                        } else
1365
 
                                return FALSE;
1366
 
                } else
1367
 
                        return FALSE;
1368
 
                break;
1369
 
        case 'O':
1370
 
                if(*pszTS == 'c') {
1371
 
                        ++pszTS;
1372
 
                        if(*pszTS == 't') {
1373
 
                                ++pszTS;
1374
 
                                pTime->month = 10;
1375
 
                        } else
1376
 
                                return FALSE;
1377
 
                } else
1378
 
                        return FALSE;
1379
 
                break;
1380
 
        case 'N':
1381
 
                if(*pszTS == 'o') {
1382
 
                        ++pszTS;
1383
 
                        if(*pszTS == 'v') {
1384
 
                                ++pszTS;
1385
 
                                pTime->month = 11;
1386
 
                        } else
1387
 
                                return FALSE;
1388
 
                } else
1389
 
                        return FALSE;
1390
 
                break;
1391
 
        case 'D':
1392
 
                if(*pszTS == 'e') {
1393
 
                        ++pszTS;
1394
 
                        if(*pszTS == 'c') {
1395
 
                                ++pszTS;
1396
 
                                pTime->month = 12;
1397
 
                        } else
1398
 
                                return FALSE;
1399
 
                } else
1400
 
                        return FALSE;
1401
 
                break;
1402
 
        default:
1403
 
                return FALSE;
1404
 
        }
1405
 
 
1406
 
        /* done month */
1407
 
 
1408
 
        if(*pszTS++ != ' ')
1409
 
                return FALSE;
1410
 
 
1411
 
        /* we accept a slightly malformed timestamp when receiving. This is
1412
 
         * we accept one-digit days
1413
 
         */
1414
 
        if(*pszTS == ' ')
1415
 
                ++pszTS;
1416
 
 
1417
 
        pTime->day = srSLMGParseInt32(&pszTS);
1418
 
        if(pTime->day < 1 || pTime->day > 31)
1419
 
                return FALSE;
1420
 
 
1421
 
        if(*pszTS++ != ' ')
1422
 
                return FALSE;
1423
 
        pTime->hour = srSLMGParseInt32(&pszTS);
1424
 
        if(pTime->hour < 0 || pTime->hour > 23)
1425
 
                return FALSE;
1426
 
 
1427
 
        if(*pszTS++ != ':')
1428
 
                return FALSE;
1429
 
        pTime->minute = srSLMGParseInt32(&pszTS);
1430
 
        if(pTime->minute < 0 || pTime->minute > 59)
1431
 
                return FALSE;
1432
 
 
1433
 
        if(*pszTS++ != ':')
1434
 
                return FALSE;
1435
 
        pTime->second = srSLMGParseInt32(&pszTS);
1436
 
        if(pTime->second < 0 || pTime->second > 60)
1437
 
                return FALSE;
1438
 
        if(*pszTS++ != ':')
1439
 
 
1440
 
        /* OK, we actually have a 3164 timestamp, so let's indicate this
1441
 
         * and fill the rest of the properties. */
1442
 
        pTime->timeType = 1;
1443
 
        pTime->secfracPrecision = 0;
1444
 
        pTime->secfrac = 0;
1445
 
        return TRUE;
1446
 
}
1447
 
 
1448
 
/*******************************************************************
1449
 
 * END CODE-LIBLOGGING                                             *
1450
 
 *******************************************************************/
1451
 
 
1452
 
/**
1453
 
 * Format a syslogTimestamp into format required by MySQL.
1454
 
 * We are using the 14 digits format. For example 20041111122600 
1455
 
 * is interpreted as '2004-11-11 12:26:00'. 
1456
 
 * The caller must provide the timestamp as well as a character
1457
 
 * buffer that will receive the resulting string. The function
1458
 
 * returns the size of the timestamp written in bytes (without
1459
 
 * the string terminator). If 0 is returend, an error occured.
1460
 
 */
1461
 
int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst)
1462
 
{
1463
 
        /* currently we do not consider localtime/utc. This may later be
1464
 
         * added. If so, I recommend using a property replacer option
1465
 
         * and/or a global configuration option. However, we should wait
1466
 
         * on user requests for this feature before doing anything.
1467
 
         * rgerhards, 2007-06-26
1468
 
         */
1469
 
        assert(ts != NULL);
1470
 
        assert(pDst != NULL);
1471
 
 
1472
 
        if (iLenDst < 15) /* we need at least 14 bytes
1473
 
                             14 digits for timestamp + '\n' */
1474
 
                return(0); 
1475
 
 
1476
 
        return(snprintf(pDst, iLenDst, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d", 
1477
 
                ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second));
1478
 
 
1479
 
}
1480
 
 
1481
 
/**
1482
 
 * Format a syslogTimestamp to a RFC3339 timestamp string (as
1483
 
 * specified in syslog-protocol).
1484
 
 * The caller must provide the timestamp as well as a character
1485
 
 * buffer that will receive the resulting string. The function
1486
 
 * returns the size of the timestamp written in bytes (without
1487
 
 * the string terminator). If 0 is returend, an error occured.
1488
 
 */
1489
 
int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
1490
 
{
1491
 
        int iRet;
1492
 
        char szTZ[7]; /* buffer for TZ information */
1493
 
 
1494
 
        assert(ts != NULL);
1495
 
        assert(pBuf != NULL);
1496
 
        
1497
 
        if(iLenBuf < 20)
1498
 
                return(0); /* we NEED at least 20 bytes */
1499
 
 
1500
 
        /* do TZ information first, this is easier to take care of "Z" zone in rfc3339 */
1501
 
        if(ts->OffsetMode == 'Z') {
1502
 
                szTZ[0] = 'Z';
1503
 
                szTZ[1] = '\0';
1504
 
        } else {
1505
 
                snprintf(szTZ, sizeof(szTZ) / sizeof(char), "%c%2.2d:%2.2d",
1506
 
                        ts->OffsetMode, ts->OffsetHour, ts->OffsetMinute);
1507
 
        }
1508
 
 
1509
 
        if(ts->secfracPrecision > 0)
1510
 
        {       /* we now need to include fractional seconds. While doing so, we must look at
1511
 
                 * the precision specified. For example, if we have millisec precision (3 digits), a
1512
 
                 * secFrac value of 12 is not equivalent to ".12" but ".012". Obviously, this
1513
 
                 * is a huge difference ;). To avoid this, we first create a format string with
1514
 
                 * the specific precision and *then* use that format string to do the actual
1515
 
                 * formating (mmmmhhh... kind of self-modifying code... ;)).
1516
 
                 */
1517
 
                char szFmtStr[64];
1518
 
                /* be careful: there is ONE actual %d in the format string below ;) */
1519
 
                snprintf(szFmtStr, sizeof(szFmtStr),
1520
 
                         "%%04d-%%02d-%%02dT%%02d:%%02d:%%02d.%%0%dd%%s",
1521
 
                        ts->secfracPrecision);
1522
 
                iRet = snprintf(pBuf, iLenBuf, szFmtStr, ts->year, ts->month, ts->day,
1523
 
                                ts->hour, ts->minute, ts->second, ts->secfrac, szTZ);
1524
 
        }
1525
 
        else
1526
 
                iRet = snprintf(pBuf, iLenBuf,
1527
 
                                "%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d%s",
1528
 
                                ts->year, ts->month, ts->day,
1529
 
                                ts->hour, ts->minute, ts->second, szTZ);
1530
 
        return(iRet);
1531
 
}
1532
 
 
1533
 
/**
1534
 
 * Format a syslogTimestamp to a RFC3164 timestamp sring.
1535
 
 * The caller must provide the timestamp as well as a character
1536
 
 * buffer that will receive the resulting string. The function
1537
 
 * returns the size of the timestamp written in bytes (without
1538
 
 * the string termnator). If 0 is returend, an error occured.
1539
 
 */
1540
 
int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
1541
 
{
1542
 
        static char* monthNames[13] = {"ERR", "Jan", "Feb", "Mar",
1543
 
                                       "Apr", "May", "Jun", "Jul",
1544
 
                                       "Aug", "Sep", "Oct", "Nov", "Dec"};
1545
 
        assert(ts != NULL);
1546
 
        assert(pBuf != NULL);
1547
 
        
1548
 
        if(iLenBuf < 16)
1549
 
                return(0); /* we NEED 16 bytes */
1550
 
        return(snprintf(pBuf, iLenBuf, "%s %2d %2.2d:%2.2d:%2.2d",
1551
 
                monthNames[ts->month], ts->day, ts->hour,
1552
 
                ts->minute, ts->second
1553
 
                ));
1554
 
}
1555
 
 
1556
 
/**
1557
 
 * Format a syslogTimestamp to a text format.
1558
 
 * The caller must provide the timestamp as well as a character
1559
 
 * buffer that will receive the resulting string. The function
1560
 
 * returns the size of the timestamp written in bytes (without
1561
 
 * the string termnator). If 0 is returend, an error occured.
1562
 
 */
1563
 
#if 0 /* This method is currently not called, be we like to preserve it */
1564
 
static int formatTimestamp(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
1565
 
{
1566
 
        assert(ts != NULL);
1567
 
        assert(pBuf != NULL);
1568
 
        
1569
 
        if(ts->timeType == 1) {
1570
 
                return(formatTimestamp3164(ts, pBuf, iLenBuf));
1571
 
        }
1572
 
 
1573
 
        if(ts->timeType == 2) {
1574
 
                return(formatTimestamp3339(ts, pBuf, iLenBuf));
1575
 
        }
1576
 
 
1577
 
        return(0);
1578
 
}
1579
 
#endif
1580
 
 
1581
 
 
1582
 
/**
1583
 
 * Get the current date/time in the best resolution the operating
1584
 
 * system has to offer (well, actually at most down to the milli-
1585
 
 * second level.
1586
 
 *
1587
 
 * The date and time is returned in separate fields as this is
1588
 
 * most portable and removes the need for additional structures
1589
 
 * (but I have to admit it is somewhat "bulky";)).
1590
 
 *
1591
 
 * Obviously, all caller-provided pointers must not be NULL...
1592
 
 */
1593
 
void getCurrTime(struct syslogTime *t)
1594
 
{
1595
 
        struct timeval tp;
1596
 
        struct tm *tm;
1597
 
        struct tm tmBuf;
1598
 
        long lBias;
1599
 
 
1600
 
        assert(t != NULL);
1601
 
        gettimeofday(&tp, NULL);
1602
 
        tm = localtime_r((time_t*) &(tp.tv_sec), &tmBuf);
1603
 
 
1604
 
        t->year = tm->tm_year + 1900;
1605
 
        t->month = tm->tm_mon + 1;
1606
 
        t->day = tm->tm_mday;
1607
 
        t->hour = tm->tm_hour;
1608
 
        t->minute = tm->tm_min;
1609
 
        t->second = tm->tm_sec;
1610
 
        t->secfrac = tp.tv_usec;
1611
 
        t->secfracPrecision = 6;
1612
 
 
1613
 
#       if __sun
1614
 
                /* Solaris uses a different method of exporting the time zone.
1615
 
                 * It is UTC - localtime, which is the opposite sign of mins east of GMT.
1616
 
                 */
1617
 
                lBias = -(daylight ? altzone : timezone);
1618
 
#       else
1619
 
                lBias = tm->tm_gmtoff;
1620
 
#       endif
1621
 
        if(lBias < 0)
1622
 
        {
1623
 
                t->OffsetMode = '-';
1624
 
                lBias *= -1;
1625
 
        }
1626
 
        else
1627
 
                t->OffsetMode = '+';
1628
 
        t->OffsetHour = lBias / 3600;
1629
 
        t->OffsetMinute = lBias % 3600;
1630
 
}
1631
 
/* rgerhards 2004-11-09: end of helper routines. On to the 
1632
 
 * "real" code ;)
1633
 
 */
1634
 
 
1635
442
 
1636
443
static int usage(void)
1637
444
{
1638
 
        fprintf(stderr, "usage: rsyslogd [-46Adhvw] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
1639
 
                " [-s domainlist] [-r[port]] [-tport[,max-sessions]] [-f conffile] [-i pidfile] [-x]\n");
 
445
        fprintf(stderr, "usage: rsyslogd [-cversion] [-46AdnqQvwx] [-lhostlist] [-sdomainlist]\n"
 
446
                        "                [-fconffile] [-ipidfile]\n"
 
447
                        "To run rsyslogd in native mode, use \"rsyslogd -c3 <other options>\"\n\n"
 
448
                        "For further information see http://www.rsyslog.com/doc\n");
1640
449
        exit(1); /* "good" exit - done to terminate usage() */
1641
450
}
1642
451
 
1643
 
#ifdef SYSLOG_UNIXAF
1644
 
static int create_unix_socket(const char *path)
1645
 
{
1646
 
        struct sockaddr_un sunx;
1647
 
        int fd;
1648
 
        char line[MAXLINE +1];
1649
 
 
1650
 
        if (path[0] == '\0')
1651
 
                return -1;
1652
 
 
1653
 
        (void) unlink(path);
1654
 
 
1655
 
        memset(&sunx, 0, sizeof(sunx));
1656
 
        sunx.sun_family = AF_UNIX;
1657
 
        (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path));
1658
 
        fd = socket(AF_UNIX, SOCK_DGRAM, 0);
1659
 
        if (fd < 0 || bind(fd, (struct sockaddr *) &sunx,
1660
 
                           SUN_LEN(&sunx)) < 0 ||
1661
 
            chmod(path, 0666) < 0) {
1662
 
                snprintf(line, sizeof(line), "cannot create %s", path);
1663
 
                logerror(line);
1664
 
                dbgprintf("cannot create %s (%d).\n", path, errno);
1665
 
                close(fd);
1666
 
                return -1;
1667
 
        }
1668
 
        return fd;
1669
 
}
1670
 
#endif
1671
 
 
1672
 
#ifdef SYSLOG_INET
1673
 
/* closes the UDP listen sockets (if they exist) and frees
1674
 
 * all dynamically assigned memory. 
1675
 
 */
1676
 
static void closeUDPListenSockets()
1677
 
{
1678
 
        register int i;
1679
 
 
1680
 
        if(finet != NULL) {
1681
 
                for (i = 0; i < *finet; i++)
1682
 
                        close(finet[i+1]);
1683
 
                free(finet);
1684
 
                finet = NULL;
1685
 
        }
1686
 
}
1687
 
 
1688
 
 
1689
 
/* creates the UDP listen sockets
1690
 
 */
1691
 
static int *create_udp_socket()
1692
 
{
1693
 
        struct addrinfo hints, *res, *r;
1694
 
        int error, maxs, *s, *socks, on = 1;
1695
 
        int sockflags;
1696
 
 
1697
 
        memset(&hints, 0, sizeof(hints));
1698
 
        hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
1699
 
        hints.ai_family = family;
1700
 
        hints.ai_socktype = SOCK_DGRAM;
1701
 
        error = getaddrinfo(NULL, LogPort, &hints, &res);
1702
 
        if(error) {
1703
 
               logerror((char*) gai_strerror(error));
1704
 
               logerror("UDP message reception disabled due to error logged in last message.\n");
1705
 
               return NULL;
1706
 
        }
1707
 
 
1708
 
        /* Count max number of sockets we may open */
1709
 
        for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
1710
 
                /* EMPTY */;
1711
 
        socks = malloc((maxs+1) * sizeof(int));
1712
 
        if (socks == NULL) {
1713
 
               logerror("couldn't allocate memory for UDP sockets, suspending UDP message reception");
1714
 
               freeaddrinfo(res);
1715
 
               return NULL;
1716
 
        }
1717
 
 
1718
 
        *socks = 0;   /* num of sockets counter at start of array */
1719
 
        s = socks + 1;
1720
 
        for (r = res; r != NULL ; r = r->ai_next) {
1721
 
               *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
1722
 
                if (*s < 0) {
1723
 
                        if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
1724
 
                                logerror("create_udp_socket(), socket");
1725
 
                                /* it is debatable if PF_INET with EAFNOSUPPORT should
1726
 
                                 * also be ignored...
1727
 
                                 */
1728
 
                        continue;
1729
 
                }
1730
 
 
1731
 
#               ifdef IPV6_V6ONLY
1732
 
                if (r->ai_family == AF_INET6) {
1733
 
                        int ion = 1;
1734
 
                        if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
1735
 
                              (char *)&ion, sizeof (ion)) < 0) {
1736
 
                        logerror("setsockopt");
1737
 
                        close(*s);
1738
 
                        *s = -1;
1739
 
                        continue;
1740
 
                        }
1741
 
                }
1742
 
#               endif
1743
 
 
1744
 
                /* if we have an error, we "just" suspend that socket. Eventually
1745
 
                 * other sockets will work. At the end of this function, we check
1746
 
                 * if we managed to open at least one socket. If not, we'll write
1747
 
                 * a "inet suspended" message and declare failure. Else we use
1748
 
                 * what we could obtain.
1749
 
                 * rgerhards, 2007-06-22
1750
 
                 */
1751
 
                if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
1752
 
                               (char *) &on, sizeof(on)) < 0 ) {
1753
 
                        logerror("setsockopt(REUSEADDR)");
1754
 
                        close(*s);
1755
 
                        *s = -1;
1756
 
                        continue;
1757
 
                }
1758
 
 
1759
 
                /* We need to enable BSD compatibility. Otherwise an attacker
1760
 
                 * could flood our log files by sending us tons of ICMP errors.
1761
 
                 */
1762
 
#ifndef BSD     
1763
 
                if (should_use_so_bsdcompat()) {
1764
 
                        if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
1765
 
                                        (char *) &on, sizeof(on)) < 0) {
1766
 
                                logerror("setsockopt(BSDCOMPAT)");
1767
 
                                close(*s);
1768
 
                                *s = -1;
1769
 
                                continue;
1770
 
                        }
1771
 
                }
1772
 
#endif
1773
 
                /* We must not block on the network socket, in case a packet
1774
 
                 * gets lost between select and recv, otherwise the process
1775
 
                 * will stall until the timeout, and other processes trying to
1776
 
                 * log will also stall.
1777
 
                 * Patch vom Colin Phipps <cph@cph.demon.co.uk> to the original
1778
 
                 * sysklogd source. Applied to rsyslogd on 2005-10-19.
1779
 
                 */
1780
 
                if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
1781
 
                        sockflags |= O_NONBLOCK;
1782
 
                        /* SETFL could fail too, so get it caught by the subsequent
1783
 
                         * error check.
1784
 
                         */
1785
 
                        sockflags = fcntl(*s, F_SETFL, sockflags);
1786
 
                }
1787
 
                if (sockflags == -1) {
1788
 
                        logerror("fcntl(O_NONBLOCK)");
1789
 
                        close(*s);
1790
 
                        *s = -1;
1791
 
                        continue;
1792
 
                }
1793
 
 
1794
 
                /* rgerhards, 2007-06-22: if we run on a kernel that does not support
1795
 
                 * the IPV6_V6ONLY socket option, we need to use a work-around. On such
1796
 
                 * systems the IPv6 socket does also accept IPv4 sockets. So an IPv4
1797
 
                 * socket can not listen on the same port as an IPv6 socket. The only
1798
 
                 * workaround is to ignore the "socket in use" error. This is what we
1799
 
                 * do if we have to.
1800
 
                 */
1801
 
                if(     (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
1802
 
#               ifndef IPV6_V6ONLY
1803
 
                     && (errno != EADDRINUSE)
1804
 
#               endif
1805
 
                   ) {
1806
 
                        logerror("bind");
1807
 
                        close(*s);
1808
 
                        *s = -1;
1809
 
                        continue;
1810
 
                }
1811
 
 
1812
 
                (*socks)++;
1813
 
                s++;
1814
 
        }
1815
 
 
1816
 
        if(res != NULL)
1817
 
               freeaddrinfo(res);
1818
 
 
1819
 
        if(Debug && *socks != maxs)
1820
 
                dbgprintf("We could initialize %d UDP listen sockets out of %d we received "
1821
 
                        "- this may or may not be an error indication.\n", *socks, maxs);
1822
 
 
1823
 
        if(*socks == 0) {
1824
 
                logerror("No UDP listen socket could successfully be initialized, "
1825
 
                         "message reception via UDP disabled.\n");
1826
 
                /* we do NOT need to free any sockets, because there were none... */
1827
 
                free(socks);
1828
 
                return(NULL);
1829
 
        }
1830
 
 
1831
 
        return(socks);
1832
 
}
1833
 
#endif
1834
 
 
1835
452
 
1836
453
/* function to destruct a selector_t object
1837
454
 * rgerhards, 2007-08-01
1838
455
 */
1839
 
static rsRetVal selectorDestruct(void *pVal)
 
456
rsRetVal
 
457
selectorDestruct(void *pVal)
1840
458
{
1841
459
        selector_t *pThis = (selector_t *) pVal;
1842
460
 
1843
461
        assert(pThis != NULL);
1844
462
 
1845
463
        if(pThis->pCSHostnameComp != NULL)
1846
 
                rsCStrDestruct(pThis->pCSHostnameComp);
 
464
                rsCStrDestruct(&pThis->pCSHostnameComp);
1847
465
        if(pThis->pCSProgNameComp != NULL)
1848
 
                rsCStrDestruct(pThis->pCSProgNameComp);
 
466
                rsCStrDestruct(&pThis->pCSProgNameComp);
1849
467
 
1850
468
        if(pThis->f_filter_type == FILTER_PROP) {
1851
469
                if(pThis->f_filterData.prop.pCSPropName != NULL)
1852
 
                        rsCStrDestruct(pThis->f_filterData.prop.pCSPropName);
 
470
                        rsCStrDestruct(&pThis->f_filterData.prop.pCSPropName);
1853
471
                if(pThis->f_filterData.prop.pCSCompValue != NULL)
1854
 
                        rsCStrDestruct(pThis->f_filterData.prop.pCSCompValue);
 
472
                        rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue);
 
473
        } else if(pThis->f_filter_type == FILTER_EXPR) {
 
474
                if(pThis->f_filterData.f_expr != NULL)
 
475
                        expr.Destruct(&pThis->f_filterData.f_expr);
1855
476
        }
1856
477
 
1857
478
        llDestroy(&pThis->llActList);
1864
485
/* function to construct a selector_t object
1865
486
 * rgerhards, 2007-08-01
1866
487
 */
1867
 
static rsRetVal selectorConstruct(selector_t **ppThis)
 
488
rsRetVal
 
489
selectorConstruct(selector_t **ppThis)
1868
490
{
1869
491
        DEFiRet;
1870
492
        selector_t *pThis;
1884
506
                }
1885
507
        }
1886
508
        *ppThis = pThis;
1887
 
        return iRet;
 
509
        RETiRet;
1888
510
}
1889
511
 
1890
512
 
1971
593
        if ( !Debug ) {
1972
594
                i = open(_PATH_TTY, O_RDWR);
1973
595
                if (i >= 0) {
1974
 
                        (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
 
596
#                       if !defined(__hpux)
 
597
                                (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
 
598
#                       else
 
599
                                /* TODO: we need to implement something for HP UX! -- rgerhards, 2008-03-04 */
 
600
                                /* actually, HP UX should have setsid, so the code directly above should
 
601
                                 * trigger. So the actual question is why it doesn't do that...
 
602
                                 */
 
603
#                       endif
1975
604
                        (void) close(i);
1976
605
                }
1977
606
        }
1979
608
#endif
1980
609
 
1981
610
 
1982
 
/* rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
 
611
/* Take a raw input line, decode the message, and print the message
 
612
 * on the appropriate log files.
 
613
 * rgerhards 2004-11-08: Please note
 
614
 * that this function does only a partial decoding. At best, it splits 
 
615
 * the PRI part. No further decode happens. The rest is done in 
 
616
 * logmsg().
 
617
 * Added the iSource parameter so that we know if we have to parse
 
618
 * HOSTNAME or not. rgerhards 2004-11-16.
 
619
 * changed parameter iSource to bParseHost. For details, see comment in
 
620
 * printchopped(). rgerhards 2005-10-06
 
621
 * rgerhards: 2008-03-06: added "flags" to allow an input module to specify
 
622
 * flags, most importantly to request ignoring the messages' timestamp.
 
623
 *
 
624
 * rgerhards, 2008-03-19:
 
625
 * I added an additional calling parameter to permit specifying the flow
 
626
 * control capability of the source.
 
627
 */
 
628
rsRetVal printline(char *hname, char *msg, int bParseHost, int flags, flowControl_t flowCtlType)
 
629
{
 
630
        DEFiRet;
 
631
        register char *p;
 
632
        int pri;
 
633
        msg_t *pMsg;
 
634
 
 
635
        /* Now it is time to create the message object (rgerhards)
 
636
        */
 
637
        CHKiRet(msgConstruct(&pMsg));
 
638
        MsgSetFlowControlType(pMsg, flowCtlType);
 
639
        MsgSetRawMsg(pMsg, msg);
 
640
        
 
641
        pMsg->bParseHOSTNAME  = bParseHost;
 
642
        /* test for special codes */
 
643
        pri = DEFUPRI;
 
644
        p = msg;
 
645
        if (*p == '<') {
 
646
                pri = 0;
 
647
                while (isdigit((int) *++p))
 
648
                {
 
649
                   pri = 10 * pri + (*p - '0');
 
650
                }
 
651
                if (*p == '>')
 
652
                        ++p;
 
653
        }
 
654
        if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
 
655
                pri = DEFUPRI;
 
656
        pMsg->iFacility = LOG_FAC(pri);
 
657
        pMsg->iSeverity = LOG_PRI(pri);
 
658
 
 
659
        /* Now we look at the HOSTNAME. That is a bit complicated...
 
660
         * If we have a locally received message, it does NOT
 
661
         * contain any hostname information in the message itself.
 
662
         * As such, the HOSTNAME is the same as the system that
 
663
         * the message was received from (that, for obvious reasons,
 
664
         * being the local host).  rgerhards 2004-11-16
 
665
         */
 
666
        if(bParseHost == 0)
 
667
                MsgSetHOSTNAME(pMsg, hname);
 
668
        MsgSetRcvFrom(pMsg, hname);
 
669
 
 
670
        /* rgerhards 2004-11-19: well, well... we've now seen that we
 
671
         * have the "hostname problem" also with the traditional Unix
 
672
         * message. As we like to emulate it, we need to add the hostname
 
673
         * to it.
 
674
         */
 
675
        if(MsgSetUxTradMsg(pMsg, p) != 0)
 
676
                ABORT_FINALIZE(RS_RET_ERR);
 
677
 
 
678
        logmsg(pMsg, flags | SYNC_FILE);
 
679
 
 
680
finalize_it:
 
681
        RETiRet;
 
682
}
 
683
 
 
684
 
 
685
/* This takes a received message that must be decoded and submits it to
 
686
 * the main message queue. The function calls the necessary parser.
 
687
 *
 
688
 * rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
1983
689
 * it tried to reassemble multi-part messages, which is a legacy stock
1984
690
 * sysklogd concept. In essence, that was that messages not ending with
1985
691
 * \0 were glued together. As far as I can see, this is a sysklogd
1998
704
 * For rfc3195 support, we needed to modify the algo for host parsing, so we can
1999
705
 * no longer rely just on the source (rfc3195d forwarded messages arrive via
2000
706
 * unix domain sockets but contain the hostname). rgerhards, 2005-10-06
 
707
 *
 
708
 * rgerhards, 2008-02-18:
 
709
 * This function was previously called "printchopped"() and has been renamed
 
710
 * as part of the effort to create a clean internal message submission interface.
 
711
 * It also has been adopted to our usual calling interface, but currently does
 
712
 * not provide any useful return states. But we now have the hook and things can
 
713
 * improve in the future. <-- TODO!
 
714
 *
 
715
 * rgerhards, 2008-03-19:
 
716
 * I added an additional calling parameter to permit specifying the flow
 
717
 * control capability of the source.
2001
718
 */
2002
 
void printchopped(char *hname, char *msg, int len, int fd, int bParseHost)
 
719
rsRetVal
 
720
parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType)
2003
721
{
 
722
        DEFiRet;
2004
723
        register int iMsg;
2005
724
        char *pMsg;
2006
725
        char *pData;
2015
734
        assert(msg != NULL);
2016
735
        assert(len >= 0);
2017
736
 
2018
 
        dbgprintf("Message length: %d, File descriptor: %d.\n", len, fd);
2019
 
 
2020
737
        /* we first check if we have a NUL character at the very end of the
2021
738
         * message. This seems to be a frequent problem with a number of senders.
2022
739
         * So I have now decided to drop these NULs. However, if they are intentional,
2062
779
                int ret;
2063
780
                iLenDefBuf = MAXLINE;
2064
781
                ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) msg+1, len-1);
2065
 
                dbgprintf("Compressed message uncompressed with status %d, length: new %d, old %d.\n",
2066
 
                        ret, iLenDefBuf, len-1);
 
782
                dbgprintf("Compressed message uncompressed with status %d, length: new %ld, old %d.\n",
 
783
                        ret, (long) iLenDefBuf, len-1);
2067
784
                /* Now check if the uncompression worked. If not, there is not much we can do. In
2068
785
                 * that case, we log an error message but ignore the message itself. Storing the
2069
786
                 * compressed text is dangerous, as it contains control characters. So we do
2073
790
                 * rgerhards, 2006-12-07
2074
791
                 */
2075
792
                if(ret != Z_OK) {
2076
 
                        logerrorInt("Uncompression of a message failed with return code %d "
 
793
                        errmsg.LogError(NO_ERRCODE, "Uncompression of a message failed with return code %d "
2077
794
                                    "- enable debug logging if you need further information. "
2078
795
                                    "Message ignored.", ret);
2079
 
                        return; /* unconditional exit, nothing left to do... */
 
796
                        FINALIZE; /* unconditional exit, nothing left to do... */
2080
797
                }
2081
798
                pData = deflateBuf;
2082
799
                pEnd = deflateBuf + iLenDefBuf;
2086
803
         * tell the user we can not accept it.
2087
804
         */
2088
805
        if(len > 0 && *msg == 'z') {
2089
 
                logerror("Received a compressed message, but rsyslogd does not have compression "
 
806
                errmsg.LogError(NO_ERRCODE, "Received a compressed message, but rsyslogd does not have compression "
2090
807
                         "support enabled. The message will be ignored.");
2091
 
                return;
 
808
                FINALIZE;
2092
809
        }       
2093
810
#       endif /* ifdef USE_NETZIP */
2094
811
 
2099
816
                         */
2100
817
                        if(iMsg == MAXLINE) {
2101
818
                                *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
2102
 
                                printline(hname, tmpline, bParseHost);
 
819
                                printline(hname, tmpline, bParseHost, flags, flowCtlType);
2103
820
                        } else {
2104
821
                                /* This case in theory never can happen. If it happens, we have
2105
822
                                 * a logic error. I am checking for it, because if I would not,
2110
827
                                 */
2111
828
                                dbgprintf("internal error: iMsg > MAXLINE in printchopped()\n");
2112
829
                        }
2113
 
                        return; /* in this case, we are done... nothing left we can do */
 
830
                        FINALIZE; /* in this case, we are done... nothing left we can do */
2114
831
                }
2115
832
                if(*pData == '\0') { /* guard against \0 characters... */
2116
833
                        /* changed to the sequence (somewhat) proposed in
2151
868
        *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
2152
869
 
2153
870
        /* typically, we should end up here! */
2154
 
        printline(hname, tmpline, bParseHost);
2155
 
 
2156
 
        return;
2157
 
}
2158
 
 
2159
 
/* Take a raw input line, decode the message, and print the message
2160
 
 * on the appropriate log files.
2161
 
 * rgerhards 2004-11-08: Please note
2162
 
 * that this function does only a partial decoding. At best, it splits 
2163
 
 * the PRI part. No further decode happens. The rest is done in 
2164
 
 * logmsg().
2165
 
 * Added the iSource parameter so that we know if we have to parse
2166
 
 * HOSTNAME or not. rgerhards 2004-11-16.
2167
 
 * changed parameter iSource to bParseHost. For details, see comment in
2168
 
 * printchopped(). rgerhards 2005-10-06
2169
 
 */
2170
 
void printline(char *hname, char *msg, int bParseHost)
2171
 
{
2172
 
        register char *p;
2173
 
        int pri;
2174
 
        msg_t *pMsg;
2175
 
 
2176
 
        /* Now it is time to create the message object (rgerhards)
2177
 
        */
2178
 
        if((pMsg = MsgConstruct()) == NULL){
2179
 
                /* rgerhards, 2007-06-21: if we can not get memory, we discard this
2180
 
                 * message but continue to run (in the hope that things improve)
2181
 
                 */
2182
 
                glblHadMemShortage = 1;
2183
 
                dbgprintf("Memory shortage in printline(): Could not construct Msg object.\n");
2184
 
                return;
2185
 
        }
2186
 
        MsgSetRawMsg(pMsg, msg);
2187
 
        
2188
 
        pMsg->bParseHOSTNAME  = bParseHost;
2189
 
        /* test for special codes */
2190
 
        pri = DEFUPRI;
2191
 
        p = msg;
2192
 
        if (*p == '<') {
2193
 
                pri = 0;
2194
 
                while (isdigit((int) *++p))
2195
 
                {
2196
 
                   pri = 10 * pri + (*p - '0');
2197
 
                }
2198
 
                if (*p == '>')
2199
 
                        ++p;
2200
 
        }
2201
 
        if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
2202
 
                pri = DEFUPRI;
2203
 
        pMsg->iFacility = LOG_FAC(pri);
2204
 
        pMsg->iSeverity = LOG_PRI(pri);
2205
 
 
2206
 
        /* Now we look at the HOSTNAME. That is a bit complicated...
2207
 
         * If we have a locally received message, it does NOT
2208
 
         * contain any hostname information in the message itself.
2209
 
         * As such, the HOSTNAME is the same as the system that
2210
 
         * the message was received from (that, for obvious reasons,
2211
 
         * being the local host).  rgerhards 2004-11-16
2212
 
         */
2213
 
        if(bParseHost == 0)
2214
 
                MsgSetHOSTNAME(pMsg, hname);
2215
 
        MsgSetRcvFrom(pMsg, hname);
2216
 
 
2217
 
        /* rgerhards 2004-11-19: well, well... we've now seen that we
2218
 
         * have the "hostname problem" also with the traditional Unix
2219
 
         * message. As we like to emulate it, we need to add the hostname
2220
 
         * to it.
2221
 
         */
2222
 
        if(MsgSetUxTradMsg(pMsg, p) != 0) return;
2223
 
 
2224
 
        logmsg(pri, pMsg, SYNC_FILE);
2225
 
 
2226
 
        /* rgerhards 2004-11-11:
2227
 
         * we are done with the message object. If it still is
2228
 
         * stored somewhere, we can call discard anyhow. This
2229
 
         * is handled via the reference count - see description
2230
 
         * of msg_t for details.
2231
 
         */
2232
 
        MsgDestruct(pMsg);
2233
 
        return;
2234
 
}
2235
 
 
2236
 
time_t  now;
 
871
        printline(hname, tmpline, bParseHost, flags, flowCtlType);
 
872
 
 
873
finalize_it:
 
874
        RETiRet;
 
875
}
2237
876
 
2238
877
/* rgerhards 2004-11-09: the following is a function that can be used
2239
878
 * to log a message orginating from the syslogd itself. In sysklogd code,
2244
883
 * function here probably is only an interim solution and that we need to
2245
884
 * think on the best way to do this.
2246
885
 */
2247
 
static void logmsgInternal(int pri, char *msg, int flags)
 
886
rsRetVal
 
887
logmsgInternal(int pri, char *msg, int flags)
2248
888
{
 
889
        DEFiRet;
2249
890
        msg_t *pMsg;
2250
891
 
2251
 
        if((pMsg = MsgConstruct()) == NULL){
2252
 
                /* rgerhards 2004-11-09: calling panic might not be the
2253
 
                 * brightest idea - however, it is the best I currently have
2254
 
                 * (think a bit more about this).
2255
 
                 * rgehards, 2007-06-21: I have now thought a bit more about
2256
 
                 * it. If we are so low on memory, there is few we can do. calling
2257
 
                 * panic so far only write a debug line - this is seomthing we keep.
2258
 
                 * Other than that, however, we ignore the error and hope that 
2259
 
                 * memory shortage will be resolved while we continue to run. In any
2260
 
                 * case, there is no valid point in aborting the syslogd for this
2261
 
                 * reason - that would be counter-productive. So we ignore the
2262
 
                 * to be logged message.
2263
 
                 */
2264
 
                glblHadMemShortage = 1;
2265
 
                dbgprintf("Memory shortage in logmsgInternal: could not construct Msg object.\n");
2266
 
                return;
2267
 
        }
2268
 
 
 
892
        CHKiRet(msgConstruct(&pMsg));
2269
893
        MsgSetUxTradMsg(pMsg, msg);
2270
894
        MsgSetRawMsg(pMsg, msg);
2271
895
        MsgSetHOSTNAME(pMsg, LocalHostName);
 
896
        MsgSetRcvFrom(pMsg, LocalHostName);
2272
897
        MsgSetTAG(pMsg, "rsyslogd:");
2273
898
        pMsg->iFacility = LOG_FAC(pri);
2274
899
        pMsg->iSeverity = LOG_PRI(pri);
2275
900
        pMsg->bParseHOSTNAME = 0;
2276
 
        getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
901
        datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
2277
902
        flags |= INTERNAL_MSG;
2278
903
 
2279
 
#ifdef USE_PTHREADS
2280
 
        if(bRunningMultithreaded == 0) { /* not yet in queued mode */
 
904
        if(bHaveMainQueue == 0) { /* not yet in queued mode */
2281
905
                iminternalAddMsg(pri, pMsg, flags);
2282
906
        } else {
2283
907
                /* we have the queue, so we can simply provide the 
2284
908
                 * message to the queue engine.
2285
909
                 */
2286
 
                logmsg(pri, pMsg, flags);
2287
 
                MsgDestruct(pMsg);
 
910
                logmsg(pMsg, flags);
2288
911
        }
2289
 
#else
2290
 
        iminternalAddMsg(pri, pMsg, flags);
2291
 
#endif
 
912
finalize_it:
 
913
        RETiRet;
2292
914
}
2293
915
 
2294
916
/* This functions looks at the given message and checks if it matches the
2298
920
 * decision code to grow more complex over time AND logmsg() is already
2299
921
 * a very lengthy function, I thought a separate function is more appropriate.
2300
922
 * 2005-09-19 rgerhards
 
923
 * 2008-02-25 rgerhards: changed interface, now utilizes iRet, bProcessMsg
 
924
 * returns is message should be procesed.
2301
925
 */
2302
 
int shouldProcessThisMessage(selector_t *f, msg_t *pMsg)
 
926
static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProcessMsg)
2303
927
{
 
928
        DEFiRet;
2304
929
        unsigned short pbMustBeFreed;
2305
930
        char *pszPropVal;
2306
 
        int iRet = 0;
 
931
        int bRet = 0;
 
932
        vm_t *pVM = NULL;
 
933
        var_t *pResult = NULL;
2307
934
 
2308
935
        assert(f != NULL);
2309
936
        assert(pMsg != NULL);
2321
948
                        /* not equal, so we are already done... */
2322
949
                        dbgprintf("hostname filter '+%s' does not match '%s'\n", 
2323
950
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
2324
 
                        return 0;
 
951
                        FINALIZE;
2325
952
                }
2326
953
        } else { /* must be -hostname */
2327
954
                if(!rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
2328
955
                        /* not equal, so we are already done... */
2329
956
                        dbgprintf("hostname filter '-%s' does not match '%s'\n", 
2330
957
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
2331
 
                        return 0;
 
958
                        FINALIZE;
2332
959
                }
2333
960
        }
2334
961
        
2349
976
                        /* not equal or inverted selection, so we are already done... */
2350
977
                        dbgprintf("programname filter '%s' does not match '%s'\n", 
2351
978
                                rsCStrGetSzStrNoNULL(f->pCSProgNameComp), getProgramName(pMsg));
2352
 
                        return 0;
 
979
                        FINALIZE;
2353
980
                }
2354
981
        }
2355
982
        
2359
986
                /* skip messages that are incorrect priority */
2360
987
                if ( (f->f_filterData.f_pmask[pMsg->iFacility] == TABLE_NOPRI) || \
2361
988
                    ((f->f_filterData.f_pmask[pMsg->iFacility] & (1<<pMsg->iSeverity)) == 0) )
2362
 
                        iRet = 0;
 
989
                        bRet = 0;
2363
990
                else
2364
 
                        iRet = 1;
 
991
                        bRet = 1;
 
992
        } else if(f->f_filter_type == FILTER_EXPR) {
 
993
                CHKiRet(vm.Construct(&pVM));
 
994
                CHKiRet(vm.ConstructFinalize(pVM));
 
995
                CHKiRet(vm.SetMsg(pVM, pMsg));
 
996
                CHKiRet(vm.ExecProg(pVM, f->f_filterData.f_expr->pVmprg));
 
997
                CHKiRet(vm.PopBoolFromStack(pVM, &pResult));
 
998
                dbgprintf("result of expression evaluation: %lld\n", pResult->val.num);
 
999
                /* VM is destructed on function exit */
 
1000
                bRet = (pResult->val.num) ? 1 : 0;
2365
1001
        } else {
2366
1002
                assert(f->f_filter_type == FILTER_PROP); /* assert() just in case... */
2367
 
                pszPropVal = MsgGetProp(pMsg, NULL,
2368
 
                                f->f_filterData.prop.pCSPropName, &pbMustBeFreed);
 
1003
                pszPropVal = MsgGetProp(pMsg, NULL, f->f_filterData.prop.pCSPropName, &pbMustBeFreed);
2369
1004
 
2370
1005
                /* Now do the compares (short list currently ;)) */
2371
1006
                switch(f->f_filterData.prop.operation ) {
2372
1007
                case FIOP_CONTAINS:
2373
1008
                        if(rsCStrLocateInSzStr(f->f_filterData.prop.pCSCompValue, (uchar*) pszPropVal) != -1)
2374
 
                                iRet = 1;
 
1009
                                bRet = 1;
2375
1010
                        break;
2376
1011
                case FIOP_ISEQUAL:
2377
1012
                        if(rsCStrSzStrCmp(f->f_filterData.prop.pCSCompValue,
2378
1013
                                          (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
2379
 
                                iRet = 1; /* process message! */
 
1014
                                bRet = 1; /* process message! */
2380
1015
                        break;
2381
1016
                case FIOP_STARTSWITH:
2382
1017
                        if(rsCStrSzStrStartsWithCStr(f->f_filterData.prop.pCSCompValue,
2383
1018
                                          (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
2384
 
                                iRet = 1; /* process message! */
 
1019
                                bRet = 1; /* process message! */
2385
1020
                        break;
2386
1021
                case FIOP_REGEX:
2387
1022
                        if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
2388
1023
                                          (unsigned char*) pszPropVal) == 0)
2389
 
                                iRet = 1;
 
1024
                                bRet = 1;
2390
1025
                        break;
2391
1026
                default:
2392
1027
                        /* here, it handles NOP (for performance reasons) */
2393
1028
                        assert(f->f_filterData.prop.operation == FIOP_NOP);
2394
 
                        iRet = 1; /* as good as any other default ;) */
 
1029
                        bRet = 1; /* as good as any other default ;) */
2395
1030
                        break;
2396
1031
                }
2397
1032
 
2398
1033
                /* now check if the value must be negated */
2399
1034
                if(f->f_filterData.prop.isNegated)
2400
 
                        iRet = (iRet == 1) ?  0 : 1;
 
1035
                        bRet = (bRet == 1) ?  0 : 1;
2401
1036
 
2402
1037
                if(Debug) {
2403
 
                        printf("Filter: check for property '%s' (value '%s') ",
 
1038
                        dbgprintf("Filter: check for property '%s' (value '%s') ",
2404
1039
                                rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName),
2405
1040
                                pszPropVal);
2406
1041
                        if(f->f_filterData.prop.isNegated)
2407
 
                                printf("NOT ");
2408
 
                        printf("%s '%s': %s\n",
 
1042
                                dbgprintf("NOT ");
 
1043
                        dbgprintf("%s '%s': %s\n",
2409
1044
                               getFIOPName(f->f_filterData.prop.operation),
2410
1045
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue),
2411
 
                               iRet ? "TRUE" : "FALSE");
 
1046
                               bRet ? "TRUE" : "FALSE");
2412
1047
                }
2413
1048
 
2414
1049
                /* cleanup */
2416
1051
                        free(pszPropVal);
2417
1052
        }
2418
1053
 
2419
 
        return(iRet);
2420
 
}
2421
 
 
2422
 
 
2423
 
/* doEmergencyLoggin()
2424
 
 * ... does exactly do that. It logs messages when the subsystem has not yet
2425
 
 * been initialized. This almost always happens during initial startup or
2426
 
 * during HUPing.  -- rgerhards, 2007-07-25
2427
 
 * rgerhards, 2007-08-03: as of now, this can normally no longer happen. All
2428
 
 * startup messages are now buffered until the system is ready to run. I leave
2429
 
 * this minimal implementation here in in the very remote case that it might
2430
 
 * be needed in the future or due to a program bug. Do *not* excpect this
2431
 
 * code to be called.
2432
 
 */
2433
 
static void doEmergencyLogging(msg_t *pMsg)
2434
 
{
2435
 
        assert(pMsg != NULL);
2436
 
        fprintf(stderr, "rsyslog: %s\n", pMsg->pszMSG);
2437
 
}
2438
 
 
2439
 
 
2440
 
/* call the configured action. Does all necessary housekeeping.
2441
 
 * rgerhards, 2007-08-01
2442
 
 */
2443
 
static rsRetVal callAction(msg_t *pMsg, action_t *pAction)
2444
 
{
2445
 
        DEFiRet;
2446
 
 
2447
 
        assert(pMsg != NULL);
2448
 
        assert(pAction != NULL);
2449
 
 
2450
 
        /* first, we need to check if this is a disabled
2451
 
         * entry. If so, we must not further process it.
2452
 
         * rgerhards 2005-09-26
2453
 
         * In the future, disabled modules may be re-probed from time
2454
 
         * to time. They are in a perfectly legal state, except that the
2455
 
         * doAction method indicated that it wanted to be disabled - but
2456
 
         * we do not consider this is a solution for eternity... So we
2457
 
         * should check from time to time if affairs have improved.
2458
 
         * rgerhards, 2007-07-24
2459
 
         */
2460
 
        if(pAction->bEnabled == 0) {
2461
 
                ABORT_FINALIZE(RS_RET_OK);
2462
 
        }
2463
 
 
2464
 
        if(actionIsSuspended(pAction)) {
2465
 
                CHKiRet(actionTryResume(pAction));
2466
 
        }
2467
 
 
2468
 
        /* don't output marks to recently written files */
2469
 
        if ((pMsg->msgFlags & MARK) && (now - pAction->f_time) < MarkInterval / 2) {
2470
 
                ABORT_FINALIZE(RS_RET_OK);
2471
 
        }
2472
 
 
2473
 
        /* suppress duplicate messages
2474
 
         */
2475
 
        if ((pAction->f_ReduceRepeated == 1) && pAction->f_pMsg != NULL &&
2476
 
            (pMsg->msgFlags & MARK) == 0 && getMSGLen(pMsg) == getMSGLen(pAction->f_pMsg) &&
2477
 
            !strcmp(getMSG(pMsg), getMSG(pAction->f_pMsg)) &&
2478
 
            !strcmp(getHOSTNAME(pMsg), getHOSTNAME(pAction->f_pMsg)) &&
2479
 
            !strcmp(getPROCID(pMsg), getPROCID(pAction->f_pMsg)) &&
2480
 
            !strcmp(getAPPNAME(pMsg), getAPPNAME(pAction->f_pMsg))) {
2481
 
                pAction->f_prevcount++;
2482
 
                dbgprintf("msg repeated %d times, %ld sec of %d.\n",
2483
 
                    pAction->f_prevcount, now - pAction->f_time,
2484
 
                    repeatinterval[pAction->f_repeatcount]);
2485
 
                MsgDestruct(pAction->f_pMsg);
2486
 
                pAction->f_pMsg = MsgAddRef(pMsg);
2487
 
                /* If domark would have logged this by now, flush it now (so we don't hold
2488
 
                 * isolated messages), but back off so we'll flush less often in the future.
2489
 
                 */
2490
 
                if (now > REPEATTIME(pAction)) {
2491
 
                        iRet = fprintlog(pAction);
2492
 
                        BACKOFF(pAction);
2493
 
                }
2494
 
        } else {
2495
 
                /* new message, save it */
2496
 
                /* first check if we have a previous message stored
2497
 
                 * if so, emit and then discard it first
2498
 
                 */
2499
 
                if(pAction->f_pMsg != NULL) {
2500
 
                        if(pAction->f_prevcount > 0)
2501
 
                                fprintlog(pAction);
2502
 
                                /* we do not care about iRet above - I think it's right but if we have
2503
 
                                 * some troubles, you know where to look at ;) -- rgerhards, 2007-08-01
2504
 
                                 */
2505
 
                        MsgDestruct(pAction->f_pMsg);
2506
 
                }
2507
 
                pAction->f_pMsg = MsgAddRef(pMsg);
2508
 
                /* call the output driver */
2509
 
                iRet = fprintlog(pAction);
2510
 
        }
2511
 
 
2512
1054
finalize_it:
2513
 
        return iRet;
 
1055
        /* destruct in any case, not just on error, but it makes error handling much easier */
 
1056
        if(pVM != NULL)
 
1057
                vm.Destruct(&pVM);
 
1058
 
 
1059
        if(pResult != NULL)
 
1060
                var.Destruct(&pResult);
 
1061
 
 
1062
        *bProcessMsg = bRet;
 
1063
        RETiRet;
2514
1064
}
2515
1065
 
2516
1066
 
2536
1086
                ABORT_FINALIZE(RS_RET_OK);
2537
1087
        }
2538
1088
 
2539
 
        iRetMod = callAction(pDoActData->pMsg, pAction);
 
1089
        iRetMod = actionCallAction(pAction, pDoActData->pMsg);
2540
1090
        if(iRetMod == RS_RET_DISCARDMSG) {
2541
1091
                ABORT_FINALIZE(RS_RET_DISCARDMSG);
2542
1092
        } else if(iRetMod == RS_RET_SUSPENDED) {
2547
1097
        }
2548
1098
 
2549
1099
finalize_it:
2550
 
        return iRet;
 
1100
        RETiRet;
2551
1101
}
2552
1102
 
2553
1103
 
2554
1104
/* Process (consume) a received message. Calls the actions configured.
2555
 
 * Can some time later run in its own thread. To aid this, the calling
2556
 
 * parameters should be reduced to just pMsg.
2557
 
 * See comment dated 2005-10-13 in logmsg() on multithreading.
2558
1105
 * rgerhards, 2005-10-13
2559
1106
 */
2560
 
static void processMsg(msg_t *pMsg)
 
1107
static void
 
1108
processMsg(msg_t *pMsg)
2561
1109
{
2562
1110
        selector_t *f;
2563
1111
        int bContinue;
 
1112
        int bProcessMsg;
2564
1113
        processMsgDoActions_t DoActData;
 
1114
        rsRetVal iRet;
2565
1115
 
 
1116
        BEGINfunc
2566
1117
        assert(pMsg != NULL);
2567
1118
 
2568
1119
        /* log the message to the particular outputs */
2569
 
        if (!Initialized) {
2570
 
                doEmergencyLogging(pMsg);
2571
 
                return;
2572
 
        }
2573
1120
 
2574
1121
        bContinue = 1;
2575
1122
        for (f = Files; f != NULL && bContinue ; f = f->f_next) {
2576
 
                /* This is actually the "filter logic". Looks like we need
2577
 
                 * to improve it a little for complex selector line conditions. We
2578
 
                 * won't do that for now, but at least we now know where
2579
 
                 * to look at.
2580
 
                 * 2005-09-09 rgerhards
2581
 
                 * ok, we are now ready to move to something more advanced. Because
2582
 
                 * of this, I am moving the actual decision code to outside this function.
2583
 
                 * 2005-09-19 rgerhards
2584
 
                 */
2585
 
                if(!shouldProcessThisMessage(f, pMsg)) {
 
1123
                /* first check the filters... */
 
1124
                iRet = shouldProcessThisMessage(f, pMsg, &bProcessMsg);
 
1125
                if(!bProcessMsg) {
2586
1126
                        continue;
2587
1127
                }
2588
1128
 
2592
1132
                if(llExecFunc(&f->llActList, processMsgDoActions, (void*)&DoActData) == RS_RET_DISCARDMSG)
2593
1133
                        bContinue = 0;
2594
1134
        }
2595
 
}
2596
 
 
2597
 
 
2598
 
#ifdef  USE_PTHREADS
2599
 
/* This block contains code that is only present when USE_PTHREADS is
2600
 
 * enabled. I plan to move it to some other file, but for the time
2601
 
 * being, I include it here because that saves me from the need to
2602
 
 * do so many external definitons.
2603
 
 * rgerhards, 2005-10-24
2604
 
 */
2605
 
 
2606
 
/* shuts down the worker process. The worker will first finish
2607
 
 * with the message queue. Control returns, when done.
2608
 
 * This function is intended to be called during syslogd shutdown
2609
 
 * AND restart (init()!).
2610
 
 * rgerhards, 2005-10-25
2611
 
 */
2612
 
static void stopWorker(void)
2613
 
{
2614
 
        if(bRunningMultithreaded) {
2615
 
                /* we could run single-threaded if there was an error
2616
 
                 * during startup. Then, we obviously do not need to
2617
 
                 * do anything to stop the worker ;)
2618
 
                 */
2619
 
                dbgprintf("Initiating worker thread shutdown sequence...\n");
2620
 
                /* We are now done with all messages, so we need to wake up the
2621
 
                 * worker thread and then wait for it to finish.
2622
 
                 */
2623
 
                bGlblDone = 1;
2624
 
                /* It's actually not "not empty" below but awaking the worker. The worker
2625
 
                 * then finds out that it shall terminate and does so.
2626
 
                 */
2627
 
                pthread_cond_signal(pMsgQueue->notEmpty);
2628
 
                pthread_join(thrdWorker, NULL);
2629
 
                bRunningMultithreaded = 0;
2630
 
                dbgprintf("Worker thread terminated.\n");
2631
 
        }
2632
 
}
2633
 
 
2634
 
 
2635
 
/* starts the worker thread. It must be made sure that the queue is
2636
 
 * already existing and the worker is NOT already running.
2637
 
 * rgerhards 2005-10-25
2638
 
 */
2639
 
static void startWorker(void)
2640
 
{
2641
 
        int i;
2642
 
        if(pMsgQueue != NULL) {
2643
 
                bGlblDone = 0; /* we are NOT done (else worker would immediately terminate) */
2644
 
                i = pthread_create(&thrdWorker, NULL, singleWorker, NULL);
2645
 
                dbgprintf("Worker thread started with state %d.\n", i);
2646
 
                bRunningMultithreaded = 1;
2647
 
        } else {
2648
 
                dbgprintf("message queue not existing, remaining single-threaded.\n");
2649
 
        }
2650
 
}
2651
 
 
2652
 
 
2653
 
static msgQueue *queueInit (void)
2654
 
{
2655
 
        msgQueue *q;
2656
 
 
2657
 
        q = (msgQueue *)malloc(sizeof(msgQueue));
2658
 
        if (q == NULL) return (NULL);
2659
 
        if((q->pbuf = malloc(sizeof(void *) * iMainMsgQueueSize)) == NULL) {
2660
 
                free(q);
2661
 
                return NULL;
2662
 
        }
2663
 
 
2664
 
        q->empty = 1;
2665
 
        q->full = 0;
2666
 
        q->head = 0;
2667
 
        q->tail = 0;
2668
 
        q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
2669
 
        pthread_mutex_init (q->mut, NULL);
2670
 
        q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
2671
 
        pthread_cond_init (q->notFull, NULL);
2672
 
        q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
2673
 
        pthread_cond_init (q->notEmpty, NULL);
2674
 
        
2675
 
        return (q);
2676
 
}
2677
 
 
2678
 
static void queueDelete (msgQueue *q)
2679
 
{
2680
 
        pthread_mutex_destroy (q->mut);
2681
 
        free (q->mut);  
2682
 
        pthread_cond_destroy (q->notFull);
2683
 
        free (q->notFull);
2684
 
        pthread_cond_destroy (q->notEmpty);
2685
 
        free (q->notEmpty);
2686
 
        free(q->pbuf);
2687
 
        free (q);
2688
 
}
2689
 
 
2690
 
 
2691
 
/* In queueAdd() and queueDel() we have a potential race condition. If a message
2692
 
 * is dequeued and at the same time a message is enqueued and the queue is either
2693
 
 * full or empty, the full (or empty) indicator may be invalidly updated. HOWEVER,
2694
 
 * this does not cause any real problems. No queue pointers can be wrong. And even
2695
 
 * if one of the flags is set invalidly, that does not pose a real problem. If
2696
 
 * "full" is invalidly set, at mose one message might be lost, if we are already in
2697
 
 * a timeout situation (this is quite acceptable). And if "empty" is accidently set,
2698
 
 * the receiver will not continue the inner loop, but break out of the outer. So no
2699
 
 * harm is done at all. For this reason, I do not yet use a mutex to guard the two
2700
 
 * flags - there would be a notable performance hit with, IMHO, no gain in stability
2701
 
 * or functionality. But anyhow, now it's documented...
2702
 
 * rgerhards, 2007-09-20
2703
 
 * NOTE: this comment does not really apply - the callers handle the mutex, so it
2704
 
 * *is* guarded.
2705
 
 */
2706
 
static void queueAdd (msgQueue *q, void* in)
2707
 
{
2708
 
        q->pbuf[q->tail] = in;
2709
 
        q->tail++;
2710
 
        if (q->tail == iMainMsgQueueSize)
2711
 
                q->tail = 0;
2712
 
        if (q->tail == q->head)
2713
 
                q->full = 1;
2714
 
        q->empty = 0;
2715
 
 
2716
 
        return;
2717
 
}
2718
 
 
2719
 
static void queueDel (msgQueue *q, msg_t **out)
2720
 
{
2721
 
        *out = (msg_t*) q->pbuf[q->head];
2722
 
 
2723
 
        q->head++;
2724
 
        if (q->head == iMainMsgQueueSize)
2725
 
                q->head = 0;
2726
 
        if (q->head == q->tail)
2727
 
                q->empty = 1;
2728
 
        q->full = 0;
2729
 
 
2730
 
        return;
2731
 
}
2732
 
 
2733
 
 
2734
 
/* The worker thread (so far, we have dual-threading, so only one
2735
 
 * worker thread. Having more than one worker requires considerable
2736
 
 * additional code review in regard to thread-safety.
2737
 
 */
2738
 
static void *singleWorker()
2739
 
{
2740
 
        msgQueue *fifo = pMsgQueue;
2741
 
        msg_t *pMsg;
2742
 
        sigset_t sigSet;
2743
 
 
2744
 
        assert(fifo != NULL);
2745
 
 
2746
 
        sigfillset(&sigSet);
2747
 
        pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
2748
 
 
2749
 
        while(!bGlblDone || !fifo->empty) {
2750
 
                pthread_mutex_lock(fifo->mut);
2751
 
                while (fifo->empty && !bGlblDone) {
2752
 
                        dbgprintf("singleWorker: queue EMPTY, waiting for next message.\n");
2753
 
                        pthread_cond_wait (fifo->notEmpty, fifo->mut);
2754
 
                }
2755
 
                if(!fifo->empty) {
2756
 
                        /* dequeue element (still protected from mutex) */
2757
 
                        queueDel(fifo, &pMsg);
2758
 
                        assert(pMsg != NULL);
2759
 
                        pthread_mutex_unlock(fifo->mut);
2760
 
                        pthread_cond_signal (fifo->notFull);
2761
 
                        /* do actual processing (the lengthy part, runs in parallel) */
2762
 
                        dbgprintf("Lone worker is running...\n");
2763
 
                        processMsg(pMsg);
2764
 
                        MsgDestruct(pMsg);
2765
 
                        /* If you need a delay for testing, here do a */
2766
 
                        /* sleep(1); */
2767
 
                } else { /* the mutex must be unlocked in any case (important for termination) */
2768
 
                        pthread_mutex_unlock(fifo->mut);
2769
 
                }
2770
 
                
2771
 
                if(debugging_on && bGlblDone && !fifo->empty)
2772
 
                        dbgprintf("Worker does not yet terminate because it still has messages to process.\n");
2773
 
        }
2774
 
 
2775
 
        dbgprintf("Worker thread terminates\n");
2776
 
        pthread_exit(0);
2777
 
}
2778
 
 
2779
 
/* END threads-related code */
2780
 
#endif /* #ifdef USE_PTHREADS */
2781
 
 
2782
 
 
2783
 
/* This method enqueues a message into the the message buffer. It also
2784
 
 * the worker thread, so that the message will be processed. If we are
2785
 
 * compiled without PTHREADS support, we simply use this method as
2786
 
 * an alias for processMsg().
2787
 
 * See comment dated 2005-10-13 in logmsg() on multithreading.
2788
 
 * rgerhards, 2005-10-24
2789
 
 */
2790
 
#ifndef USE_PTHREADS
2791
 
#define enqueueMsg(x) processMsg((x))
2792
 
#else
2793
 
static void enqueueMsg(msg_t *pMsg)
2794
 
{
2795
 
        int iRet;
2796
 
        msgQueue *fifo = pMsgQueue;
2797
 
        struct timespec t;
 
1135
        ENDfunc
 
1136
}
 
1137
 
 
1138
 
 
1139
/* The consumer of dequeued messages. This function is called by the
 
1140
 * queue engine on dequeueing of a message. It runs on a SEPARATE
 
1141
 * THREAD.
 
1142
 * NOTE: Having more than one worker requires guarding of some
 
1143
 * message object structures and potentially others - need to be checked
 
1144
 * before we support multiple worker threads on the message queue.
 
1145
 * Please note: the message object is destructed by the queue itself!
 
1146
 */
 
1147
static rsRetVal
 
1148
msgConsumer(void __attribute__((unused)) *notNeeded, void *pUsr)
 
1149
{
 
1150
        DEFiRet;
 
1151
        msg_t *pMsg = (msg_t*) pUsr;
2798
1152
 
2799
1153
        assert(pMsg != NULL);
2800
1154
 
2801
 
        if(bRunningMultithreaded == 0) {
2802
 
                /* multi-threading is not yet initialized, happens e.g.
2803
 
                 * during startup and restart. rgerhards, 2005-10-25
2804
 
                 */
2805
 
                 dbgprintf("enqueueMsg: not yet running on multiple threads\n");
2806
 
                 processMsg(pMsg);
2807
 
        } else {
2808
 
                /* "normal" mode, threading initialized */
2809
 
                pthread_mutex_lock(fifo->mut);
2810
 
                        
2811
 
                while (fifo->full) {
2812
 
                        dbgprintf("enqueueMsg: queue FULL.\n");
2813
 
                        
2814
 
                        clock_gettime (CLOCK_REALTIME, &t);
2815
 
                        t.tv_sec += 2;
2816
 
                        
2817
 
                        if(pthread_cond_timedwait (fifo->notFull,
2818
 
                                                   fifo->mut, &t) != 0) {
2819
 
                                dbgprintf("enqueueMsg: cond timeout, dropping message!\n");
2820
 
                                goto unlock;
2821
 
                        }
2822
 
                }
2823
 
                queueAdd(fifo, MsgAddRef(pMsg));
2824
 
        unlock:
2825
 
                /* now activate the worker thread */
2826
 
                pthread_mutex_unlock(fifo->mut);
2827
 
                iRet = pthread_cond_signal(fifo->notEmpty);
2828
 
                dbgprintf("EnqueueMsg signaled condition (%d)\n", iRet);
2829
 
        }
 
1155
        processMsg(pMsg);
 
1156
        msgDestruct(&pMsg);
 
1157
 
 
1158
        RETiRet;
2830
1159
}
2831
 
#endif /* #ifndef USE_PTHREADS */
2832
1160
 
2833
1161
 
2834
1162
/* Helper to parseRFCSyslogMsg. This function parses a field up to
2975
1303
         */
2976
1304
 
2977
1305
        /* TIMESTAMP */
2978
 
        if(srSLMGParseTIMESTAMP3339(&(pMsg->tTIMESTAMP),  &p2parse) == FALSE) {
 
1306
        if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP),  &p2parse) == FALSE) {
2979
1307
                dbgprintf("no TIMESTAMP detected!\n");
2980
1308
                bContParse = 0;
2981
1309
                flags |= ADDDATE;
2982
1310
        }
2983
1311
 
2984
1312
        if (flags & ADDDATE) {
2985
 
                getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
1313
                datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
2986
1314
        }
2987
1315
 
2988
1316
        /* HOSTNAME */
3023
1351
        /* MSG */
3024
1352
        MsgSetMSG(pMsg, p2parse);
3025
1353
 
 
1354
        free(pBuf);
3026
1355
        return 0; /* all ok */
3027
1356
}
 
1357
 
 
1358
 
3028
1359
/* parse a legay-formatted syslog message. This function returns
3029
1360
 * 0 if processing of the message shall continue and 1 if something
3030
1361
 * went wrong and this messe should be ignored. This function has been
3043
1374
        char *p2parse;
3044
1375
        char *pBuf;
3045
1376
        char *pWork;
3046
 
        rsCStrObj *pStrB;
 
1377
        cstr_t *pStrB;
3047
1378
        int iCnt;
3048
1379
        int bTAGCharDetected;
3049
1380
 
3051
1382
        assert(pMsg->pszUxTradMsg != NULL);
3052
1383
        p2parse = (char*) pMsg->pszUxTradMsg;
3053
1384
 
3054
 
        /* Check to see if msg contains a timestamp
 
1385
        /* Check to see if msg contains a timestamp. We stary trying with a
 
1386
         * high-precision one...
3055
1387
         */
3056
 
        if(srSLMGParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
 
1388
        if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE)
 
1389
                /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */;
 
1390
        else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
3057
1391
                p2parse += 16;
3058
1392
        else {
3059
1393
                flags |= ADDDATE;
3064
1398
         * MSG part of the message (as of RFC 3164).
3065
1399
         * rgerhards 2004-12-03
3066
1400
         */
3067
 
        (void) time(&now);
3068
 
        if (flags & ADDDATE) {
3069
 
                getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
1401
        if(flags & ADDDATE) {
 
1402
                datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
3070
1403
        }
3071
1404
 
3072
1405
        /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we 
3076
1409
         * machine that we received the message from and the tag will be empty. This
3077
1410
         * is meant to be an interim solution, but for now it is in the code.
3078
1411
         */
3079
 
 
3080
1412
        if(bParseHOSTNAMEandTAG && !(flags & INTERNAL_MSG)) {
3081
1413
                /* parse HOSTNAME - but only if this is network-received!
3082
1414
                 * rger, 2005-11-14: we still have a problem with BSD messages. These messages
3116
1448
                         */
3117
1449
                        if(*p2parse == ':') {
3118
1450
                                bTAGCharDetected = 1;
3119
 
                                ++p2parse;
 
1451
                                /* We will move hostname to tag, so preserve ':' (otherwise we 
 
1452
                                 * will needlessly change the message format) */
 
1453
                                *pWork++ = *p2parse++; 
3120
1454
                        } else if(*p2parse == ' ')
3121
1455
                                ++p2parse;
3122
1456
                        *pWork = '\0';
3132
1466
                        MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
3133
1467
                }
3134
1468
 
3135
 
                /* now parse TAG - that should be present in message from
3136
 
                 * all sources.
 
1469
                /* now parse TAG - that should be present in message from all sources.
3137
1470
                 * This code is somewhat not compliant with RFC 3164. As of 3164,
3138
1471
                 * the TAG field is ended by any non-alphanumeric character. In
3139
1472
                 * practice, however, the TAG often contains dashes and other things,
3140
1473
                 * which would end the TAG. So it is not desirable. As such, we only
3141
1474
                 * accept colon and SP to be terminators. Even there is a slight difference:
3142
1475
                 * a colon is PART of the TAG, while a SP is NOT part of the tag
3143
 
                 * (it is CONTENT). Finally, we allow only up to 32 characters for
3144
 
                 * TAG, as it is specified in RFC 3164.
 
1476
                 * (it is CONTENT). Starting 2008-04-04, we have removed the 32 character
 
1477
                 * size limit (from RFC3164) on the tag. This had bad effects on existing
 
1478
                 * envrionments, as sysklogd didn't obey it either (probably another bug
 
1479
                 * in RFC3164...). We now receive the full size, but will modify the
 
1480
                 * outputs so that only 32 characters max are used by default.
3145
1481
                 */
3146
1482
                /* The following code in general is quick & dirty - I need to get
3147
1483
                 * it going for a test, rgerhards 2004-11-16 */
3150
1486
                 * the records: the code is currently clean, but we could optimize it! */
3151
1487
                if(!bTAGCharDetected) {
3152
1488
                        uchar *pszTAG;
3153
 
                        if((pStrB = rsCStrConstruct()) == NULL) 
 
1489
                        if(rsCStrConstruct(&pStrB) != RS_RET_OK) 
3154
1490
                                return 1;
3155
1491
                        rsCStrSetAllocIncrement(pStrB, 33);
3156
1492
                        pWork = pBuf;
3157
1493
                        iCnt = 0;
3158
 
                        while(*p2parse && *p2parse != ':' && *p2parse != ' ' && iCnt < 32) {
 
1494
                        while(*p2parse && *p2parse != ':' && *p2parse != ' ') {
3159
1495
                                rsCStrAppendChar(pStrB, *p2parse++);
3160
1496
                                ++iCnt;
3161
1497
                        }
3203
1539
}
3204
1540
 
3205
1541
 
 
1542
/* submit a fully created message to the main message queue. The message is
 
1543
 * fully processed and parsed, so no parsing at all happens. This is primarily
 
1544
 * a hook to prevent the need for callers to know about the main message queue
 
1545
 * (which may change in the future as we will probably have multiple rule
 
1546
 * sets and thus queues...).
 
1547
 * rgerhards, 2008-02-13
 
1548
 */
 
1549
rsRetVal
 
1550
submitMsg(msg_t *pMsg)
 
1551
{
 
1552
        DEFiRet;
 
1553
 
 
1554
        ISOBJ_TYPE_assert(pMsg, msg);
 
1555
        
 
1556
        MsgPrepareEnqueue(pMsg);
 
1557
        queueEnqObj(pMsgQueue, pMsg->flowCtlType, (void*) pMsg);
 
1558
 
 
1559
        RETiRet;
 
1560
}
 
1561
 
 
1562
 
3206
1563
/*
3207
1564
 * Log a message to the appropriate log files, users, etc. based on
3208
1565
 * the priority.
3222
1579
 * potential for misinterpretation, which we simply can not solve under the
3223
1580
 * circumstances given.
3224
1581
 */
3225
 
void logmsg(int pri, msg_t *pMsg, int flags)
 
1582
void
 
1583
logmsg(msg_t *pMsg, int flags)
3226
1584
{
3227
1585
        char *msg;
3228
 
        char PRItext[20];
3229
1586
 
 
1587
        BEGINfunc
3230
1588
        assert(pMsg != NULL);
3231
1589
        assert(pMsg->pszUxTradMsg != NULL);
3232
1590
        msg = (char*) pMsg->pszUxTradMsg;
3233
 
        dbgprintf("logmsg: %s, flags %x, from '%s', msg %s\n",
3234
 
                textpri(PRItext, sizeof(PRItext) / sizeof(char), pri),
3235
 
                flags, getRcvFrom(pMsg), msg);
 
1591
        dbgprintf("logmsg: flags %x, from '%s', msg %s\n", flags, getRcvFrom(pMsg), msg);
3236
1592
 
3237
1593
        /* rger 2005-11-24 (happy thanksgiving!): we now need to check if we have
3238
1594
         * a traditional syslog message or one formatted according to syslog-protocol.
3242
1598
        if(msg[0] == '1' && msg[1] == ' ') {
3243
1599
                dbgprintf("Message has syslog-protocol format.\n");
3244
1600
                setProtocolVersion(pMsg, 1);
3245
 
                if(parseRFCSyslogMsg(pMsg, flags) == 1)
 
1601
                if(parseRFCSyslogMsg(pMsg, flags) == 1) {
 
1602
                        msgDestruct(&pMsg);
3246
1603
                        return;
 
1604
                }
3247
1605
        } else { /* we have legacy syslog */
3248
1606
                dbgprintf("Message has legacy syslog format.\n");
3249
1607
                setProtocolVersion(pMsg, 0);
3250
 
                if(parseLegacySyslogMsg(pMsg, flags) == 1)
 
1608
                if(parseLegacySyslogMsg(pMsg, flags) == 1) {
 
1609
                        msgDestruct(&pMsg);
3251
1610
                        return;
 
1611
                }
3252
1612
        }
3253
1613
 
3254
1614
        /* ---------------------- END PARSING ---------------- */
3255
 
 
3256
 
        /* rgerhards, 2005-10-13: if we consider going multi-threaded, this
3257
 
         * is probably the best point to split between a producer and a consumer
3258
 
         * thread. In general, with the first multi-threaded approach, we should
3259
 
         * NOT try to do more than have a single producer and consumer, at least
3260
 
         * if both are from the current code base. The issue is that this code
3261
 
         * was definitely not written with reentrancy in mind and uses a lot of
3262
 
         * global variables. So it is very dangerous to simply go ahead and multi
3263
 
         * thread it. However, I think there is a clear distinction between
3264
 
         * producer (where data is received) and consumer (where the actions are).
3265
 
         * It should be fairly safe to create a single thread for each and run them
3266
 
         * concurrently, thightly coupled via an in-memory queue. Even with this 
3267
 
         * limited multithraeding, benefits are immediate: the lengthy actions
3268
 
         * (database writes!) are de-coupled from the receivers, what should result
3269
 
         * in less likely message loss (loss due to receiver overrun). It also allows
3270
 
         * us to utilize 2-cpu systems, which will soon be common given the current
3271
 
         * advances in multicore CPU hardware. So this is well worth trying.
3272
 
         * Another plus of this two-thread-approach would be that it can easily be configured,
3273
 
         * so if there are compatibility issues with the threading libs, we could simply
3274
 
         * disable it (as a makefile feature).
3275
 
         * There is one important thing to keep in mind when doing this basic
3276
 
         * multithreading. The syslog/tcp message forwarder manipulates a structutre
3277
 
         * that is used by the main thread, which actually sends the data. This
3278
 
         * structure must be guarded by a mutex, else we will have race conditions and
3279
 
         * some very bad things could happen.
3280
 
         *
3281
 
         * Additional consumer threads might be added relatively easy for new receivers,
3282
 
         * e.g. if we decide to move RFC 3195 via liblogging natively into rsyslogd.
3283
 
         *
3284
 
         * To aid this functionality, I am moving the rest of the code (the actual
3285
 
         * consumer) to its own method, now called "processMsg()".
3286
 
         *
3287
 
         * rgerhards, 2005-10-25: as of now, the dual-threading code is now in place.
3288
 
         * It is an optional feature and even when enabled, rsyslogd will run single-threaded
3289
 
         * if it gets any errors during thread creation.
3290
 
         */
3291
1615
        
 
1616
        /* now submit the message to the main queue - then we are done */
3292
1617
        pMsg->msgFlags = flags;
3293
 
        enqueueMsg(pMsg);
3294
 
}
3295
 
 
3296
 
 
3297
 
/* rgerhards 2004-11-09: fprintlog() is the actual driver for
3298
 
 * the output channel. It receives the channel description (f) as
3299
 
 * well as the message and outputs them according to the channel
3300
 
 * semantics. The message is typically already contained in the
3301
 
 * channel save buffer (f->f_prevline). This is not only the case
3302
 
 * when a message was already repeated but also when a new message
3303
 
 * arrived.
3304
 
 * rgerhards 2007-08-01: interface changed to use action_t
3305
 
 */
3306
 
rsRetVal fprintlog(action_t *pAction)
3307
 
{
3308
 
        msg_t *pMsgSave;        /* to save current message pointer, necessary to restore
3309
 
                                   it in case it needs to be updated (e.g. repeated msgs) */
3310
 
        pMsgSave = NULL;        /* indicate message poiner not saved */
3311
 
        DEFiRet;
3312
 
        int i;
3313
 
 
3314
 
        /* first check if this is a regular message or the repeation of
3315
 
         * a previous message. If so, we need to change the message text
3316
 
         * to "last message repeated n times" and then go ahead and write
3317
 
         * it. Please note that we can not modify the message object, because
3318
 
         * that would update it in other selectors as well. As such, we first
3319
 
         * need to create a local copy of the message, which we than can update.
3320
 
         * rgerhards, 2007-07-10
3321
 
         */
3322
 
        if(pAction->f_prevcount > 1) {
3323
 
                msg_t *pMsg;
3324
 
                uchar szRepMsg[64];
3325
 
                snprintf((char*)szRepMsg, sizeof(szRepMsg), "last message repeated %d times",
3326
 
                    pAction->f_prevcount);
3327
 
 
3328
 
                if((pMsg = MsgDup(pAction->f_pMsg)) == NULL) {
3329
 
                        /* it failed - nothing we can do against it... */
3330
 
                        dbgprintf("Message duplication failed, dropping repeat message.\n");
3331
 
                        return RS_RET_ERR;
3332
 
                        /* This return is OK. The finalizer frees strings, which are not
3333
 
                         * yet allocated. So we can not use the finalizer.
3334
 
                         */
3335
 
                }
3336
 
 
3337
 
                /* We now need to update the other message properties.
3338
 
                 * ... RAWMSG is a problem ... Please note that digital
3339
 
                 * signatures inside the message are also invalidated.
3340
 
                 */
3341
 
                getCurrTime(&(pMsg->tRcvdAt));
3342
 
                getCurrTime(&(pMsg->tTIMESTAMP));
3343
 
                MsgSetMSG(pMsg, (char*)szRepMsg);
3344
 
                MsgSetRawMsg(pMsg, (char*)szRepMsg);
3345
 
 
3346
 
                pMsgSave = pAction->f_pMsg;     /* save message pointer for later restoration */
3347
 
                pAction->f_pMsg = pMsg; /* use the new msg (pointer will be restored below) */
3348
 
        }
3349
 
 
3350
 
        dbgprintf("Called fprintlog, logging to %s", modGetStateName(pAction->pMod));
3351
 
 
3352
 
        pAction->f_time = now; /* we need this for message repeation processing TODO: why must "now" be global? */
3353
 
 
3354
 
        /* When we reach this point, we have a valid, non-disabled action.
3355
 
         * So let's execute it. -- rgerhards, 2007-07-24
3356
 
         */
3357
 
        /* here we must loop to process all requested strings */
3358
 
 
3359
 
        for(i = 0 ; i < pAction->iNumTpls ; ++i) {
3360
 
                CHKiRet(tplToString(pAction->ppTpl[i], pAction->f_pMsg, &pAction->ppMsgs[i]));
3361
 
        }
3362
 
        /* call configured action */
3363
 
        iRet = pAction->pMod->mod.om.doAction(pAction->ppMsgs, pAction->f_pMsg->msgFlags, pAction->pModData);
3364
 
 
3365
 
        if(iRet == RS_RET_DISABLE_ACTION) {
3366
 
                dbgprintf("Action requested to be disabled, done that.\n");
3367
 
                pAction->bEnabled = 0; /* that's it... */
3368
 
        }
3369
 
 
3370
 
        if(iRet == RS_RET_SUSPENDED) {
3371
 
                dbgprintf("Action requested to be suspended, done that.\n");
3372
 
                actionSuspend(pAction);
3373
 
        }
3374
 
 
3375
 
        if(iRet == RS_RET_OK)
3376
 
                pAction->f_prevcount = 0; /* message process, so we start a new cycle */
3377
 
 
3378
 
finalize_it:
3379
 
        /* cleanup */
3380
 
        for(i = 0 ; i < pAction->iNumTpls ; ++i) {
3381
 
                if(pAction->ppMsgs[i] != NULL) {
3382
 
                        free(pAction->ppMsgs[i]);
3383
 
                        pAction->ppMsgs[i] = NULL;
3384
 
                }
3385
 
        }
3386
 
 
3387
 
        if(pMsgSave != NULL) {
3388
 
                /* we had saved the original message pointer. That was
3389
 
                 * done because we needed to create a temporary one
3390
 
                 * (most often for "message repeated n time" handling. If so,
3391
 
                 * we need to restore the original one now, so that procesing
3392
 
                 * can continue as normal. We also need to discard the temporary
3393
 
                 * one, as we do not like memory leaks ;) Please note that the original
3394
 
                 * message object will be discarded by our callers, so this is nothing
3395
 
                 * of our buisiness. rgerhards, 2007-07-10
3396
 
                 */
3397
 
                MsgDestruct(pAction->f_pMsg);
3398
 
                pAction->f_pMsg = pMsgSave;     /* restore it */
3399
 
        }
3400
 
 
3401
 
        return iRet;
3402
 
}
3403
 
 
3404
 
 
3405
 
static void reapchild()
 
1618
        MsgPrepareEnqueue(pMsg);
 
1619
        queueEnqObj(pMsgQueue, pMsg->flowCtlType, (void*) pMsg);
 
1620
        ENDfunc
 
1621
}
 
1622
 
 
1623
 
 
1624
static void
 
1625
reapchild()
3406
1626
{
3407
1627
        int saved_errno = errno;
3408
1628
        struct sigaction sigAct;
3417
1637
}
3418
1638
 
3419
1639
 
3420
 
/* helper to domark to flush the individual action links via llExecFunc
 
1640
/* helper to doFlushRptdMsgs() to flush the individual action links via llExecFunc
3421
1641
 * rgerhards, 2007-08-02
3422
1642
 */
3423
 
DEFFUNC_llExecFunc(domarkActions)
 
1643
DEFFUNC_llExecFunc(flushRptdMsgsActions)
3424
1644
{
3425
1645
        action_t *pAction = (action_t*) pData;
3426
1646
 
3427
1647
        assert(pAction != NULL);
3428
 
 
3429
 
        if (pAction->f_prevcount && now >= REPEATTIME(pAction)) {
 
1648
        
 
1649
        BEGINfunc
 
1650
        LockObj(pAction);
 
1651
        if (pAction->f_prevcount && time(NULL) >= REPEATTIME(pAction)) {
3430
1652
                dbgprintf("flush %s: repeated %d times, %d sec.\n",
3431
 
                    modGetStateName(pAction->pMod), pAction->f_prevcount,
 
1653
                    module.GetStateName(pAction->pMod), pAction->f_prevcount,
3432
1654
                    repeatinterval[pAction->f_repeatcount]);
3433
 
                fprintlog(pAction);
 
1655
                actionWriteToAction(pAction);
3434
1656
                BACKOFF(pAction);
3435
1657
        }
 
1658
        UnlockObj(pAction);
3436
1659
 
 
1660
        ENDfunc
3437
1661
        return RS_RET_OK; /* we ignore errors, we can not do anything either way */
3438
1662
}
3439
1663
 
3440
1664
 
3441
 
/* This method writes mark messages and - some time later - flushes reapeat
3442
 
 * messages.
3443
 
 * This method was initially called by an alarm handler. As such, it could potentially
3444
 
 * have  race-conditons. For details, see
3445
 
 * http://lkml.org/lkml/2005/3/26/37
3446
 
 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=301511
3447
 
 * I have now changed it so that the alarm handler only sets a global variable, telling
3448
 
 * the main thread that it must do mark processing. So domark() is now called from the
3449
 
 * main thread itself, which is the only thing to make sure rsyslogd will not do
3450
 
 * strange things. The way it originally was seemed to work because mark occurs very
3451
 
 * seldom. However, the code called was anything else but reentrant, so it was like
3452
 
 * russian roulette.
3453
 
 * rgerhards, 2005-10-20
 
1665
/* This method flushes reapeat messages.
3454
1666
 */
3455
 
static void domark(void)
 
1667
static void
 
1668
doFlushRptdMsgs(void)
3456
1669
{
3457
1670
        register selector_t *f;
3458
1671
 
3459
 
        if (MarkInterval > 0) {
3460
 
                now = time(NULL);
3461
 
                MarkSeq += TIMERINTVL;
3462
 
                if (MarkSeq >= MarkInterval) {
3463
 
                        logmsgInternal(LOG_INFO, "-- MARK --", ADDDATE|MARK);
3464
 
                        MarkSeq = 0;
3465
 
                }
3466
 
 
3467
 
                /* see if we need to flush any "message repeated n times"... */
3468
 
                for (f = Files; f != NULL ; f = f->f_next) {
3469
 
                        llExecFunc(&f->llActList, domarkActions, NULL);
3470
 
                }
 
1672
        /* see if we need to flush any "message repeated n times"... 
 
1673
         * Note that this interferes with objects running on other threads.
 
1674
         * We are using appropriate locking inside the function to handle that.
 
1675
         */
 
1676
        for (f = Files; f != NULL ; f = f->f_next) {
 
1677
                llExecFunc(&f->llActList, flushRptdMsgsActions, NULL);
3471
1678
        }
3472
1679
}
3473
1680
 
3474
1681
 
3475
 
/* This is the alarm handler setting the global variable for
3476
 
 * domark request. See domark() comments for further details.
3477
 
 * rgerhards, 2005-10-20
3478
 
 */
3479
 
static void domarkAlarmHdlr()
3480
 
{
3481
 
        struct sigaction sigAct;
3482
 
 
3483
 
        bRequestDoMark = 1; /* request alarm */
3484
 
 
3485
 
        memset(&sigAct, 0, sizeof (sigAct));
3486
 
        sigemptyset(&sigAct.sa_mask);
3487
 
        sigAct.sa_handler = domarkAlarmHdlr;
3488
 
        sigaction(SIGALRM, &sigAct, NULL);
3489
 
 
3490
 
        (void) alarm(TIMERINTVL);
3491
 
}
3492
 
 
3493
 
 
3494
1682
static void debug_switch()
3495
1683
{
3496
1684
        struct sigaction sigAct;
3497
1685
 
3498
 
        dbgprintf("Switching debugging_on to %s\n", (debugging_on == 0) ? "true" : "false");
3499
 
        debugging_on = (debugging_on == 0) ? 1 : 0;
 
1686
        if(debugging_on == 0) {
 
1687
                debugging_on = 1;
 
1688
                dbgprintf("Switching debugging_on to true\n");
 
1689
        } else {
 
1690
                dbgprintf("Switching debugging_on to false\n");
 
1691
                debugging_on = 0;
 
1692
        }
3500
1693
        
3501
1694
        memset(&sigAct, 0, sizeof (sigAct));
3502
1695
        sigemptyset(&sigAct.sa_mask);
3505
1698
}
3506
1699
 
3507
1700
 
3508
 
/*
3509
 
 * Add a string to error message and send it to logerror()
3510
 
 * The error message is passed to snprintf() and must be
3511
 
 * correctly formatted for it (containing a single %s param).
3512
 
 * rgerhards 2005-09-19
3513
 
 */
3514
 
void logerrorSz(char *type, char *errMsg)
3515
 
{
3516
 
        char buf[1024];
3517
 
 
3518
 
        snprintf(buf, sizeof(buf), type, errMsg);
3519
 
        buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
3520
 
        logerror(buf);
3521
 
        return;
3522
 
}
3523
 
 
3524
 
/*
3525
 
 * Add an integer to error message and send it to logerror()
3526
 
 * The error message is passed to snprintf() and must be
3527
 
 * correctly formatted for it (containing a single %d param).
3528
 
 * rgerhards 2005-09-19
3529
 
 */
3530
 
void logerrorInt(char *type, int errCode)
3531
 
{
3532
 
        char buf[1024];
3533
 
 
3534
 
        snprintf(buf, sizeof(buf), type, errCode);
3535
 
        buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
3536
 
        logerror(buf);
3537
 
        return;
3538
 
}
3539
 
 
3540
 
/* Print syslogd errors some place.
3541
 
 */
3542
 
void logerror(char *type)
3543
 
{
3544
 
        char buf[1024];
3545
 
        char errStr[1024];
3546
 
 
3547
 
        dbgprintf("Called logerr, msg: %s\n", type);
3548
 
 
3549
 
        if (errno == 0)
3550
 
                snprintf(buf, sizeof(buf), "%s", type);
 
1701
void legacyOptsEnq(uchar *line)
 
1702
{
 
1703
        legacyOptsLL_t *pNew;
 
1704
 
 
1705
        pNew = malloc(sizeof(legacyOptsLL_t));
 
1706
        if(line == NULL)
 
1707
                pNew->line = NULL;
3551
1708
        else
3552
 
                snprintf(buf, sizeof(buf), "%s: %s", type, strerror_r(errno, errStr, sizeof(errStr)));
3553
 
        buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
3554
 
        errno = 0;
3555
 
        logmsgInternal(LOG_SYSLOG|LOG_ERR, buf, ADDDATE);
3556
 
        return;
3557
 
}
 
1709
                pNew->line = (uchar *) strdup((char *) line);
 
1710
        pNew->next = NULL;
 
1711
 
 
1712
        if(pLegacyOptsLL == NULL)
 
1713
                pLegacyOptsLL = pNew;
 
1714
        else {
 
1715
                legacyOptsLL_t *pThis = pLegacyOptsLL;
 
1716
 
 
1717
                while(pThis->next != NULL)
 
1718
                        pThis = pThis->next;
 
1719
                pThis->next = pNew;
 
1720
        }
 
1721
}
 
1722
 
 
1723
 
 
1724
void legacyOptsFree(void)
 
1725
{
 
1726
        legacyOptsLL_t *pThis = pLegacyOptsLL, *pNext;
 
1727
 
 
1728
        while(pThis != NULL) {
 
1729
                if(pThis->line != NULL)
 
1730
                        free(pThis->line);
 
1731
                pNext = pThis->next;
 
1732
                free(pThis);
 
1733
                pThis = pNext;
 
1734
        }
 
1735
}
 
1736
 
 
1737
 
 
1738
void legacyOptsHook(void)
 
1739
{
 
1740
        legacyOptsLL_t *pThis = pLegacyOptsLL;
 
1741
 
 
1742
        while(pThis != NULL) {
 
1743
                if(pThis->line != NULL) {
 
1744
                        errno = 0;
 
1745
                        errmsg.LogError(NO_ERRCODE, "Warning: backward compatibility layer added to following "
 
1746
                                        "directive to rsyslog.conf: %s", pThis->line);
 
1747
                        conf.cfsysline(pThis->line);
 
1748
                }
 
1749
                pThis = pThis->next;
 
1750
        }
 
1751
}
 
1752
 
 
1753
 
 
1754
void legacyOptsParseTCP(char ch, char *arg)
 
1755
{
 
1756
        register int i;
 
1757
        register char *pArg = arg;
 
1758
        static char conflict = '\0';
 
1759
 
 
1760
        if((conflict == 'g' && ch == 't') || (conflict == 't' && ch == 'g')) {
 
1761
                fprintf(stderr, "rsyslog: If you want to use both -g and -t, use directives instead, -%c ignored.\n", ch);
 
1762
                return;
 
1763
        } else
 
1764
                conflict = ch;
 
1765
 
 
1766
        /* extract port */
 
1767
        i = 0;
 
1768
        while(isdigit((int) *pArg))
 
1769
                i = i * 10 + *pArg++ - '0';
 
1770
 
 
1771
        /* number of sessions */
 
1772
        if(*pArg == '\0' || *pArg == ',') {
 
1773
                if(ch == 't')
 
1774
                        legacyOptsEnq((uchar *) "ModLoad imtcp");
 
1775
                else if(ch == 'g')
 
1776
                        legacyOptsEnq((uchar *) "ModLoad imgssapi");
 
1777
 
 
1778
                if(i >= 0 && i <= 65535) {
 
1779
                        uchar line[30];
 
1780
 
 
1781
                        if(ch == 't') {
 
1782
                                snprintf((char *) line, sizeof(line), "InputTCPServerRun %d", i);
 
1783
                        } else if(ch == 'g') {
 
1784
                                snprintf((char *) line, sizeof(line), "InputGSSServerRun %d", i);
 
1785
                        }
 
1786
                        legacyOptsEnq(line);
 
1787
                } else {
 
1788
                        if(ch == 't') {
 
1789
                                fprintf(stderr, "rsyslogd: Invalid TCP listen port %d - changed to 514.\n", i);
 
1790
                                legacyOptsEnq((uchar *) "InputTCPServerRun 514");
 
1791
                        } else if(ch == 'g') {
 
1792
                                fprintf(stderr, "rsyslogd: Invalid GSS listen port %d - changed to 514.\n", i);
 
1793
                                legacyOptsEnq((uchar *) "InputGSSServerRun 514");
 
1794
                        }
 
1795
                }
 
1796
 
 
1797
                if(*pArg == ',') {
 
1798
                        ++pArg;
 
1799
                        while(isspace((int) *pArg))
 
1800
                                ++pArg;
 
1801
                        i = 0;
 
1802
                        while(isdigit((int) *pArg)) {
 
1803
                                i = i * 10 + *pArg++ - '0';
 
1804
                        }
 
1805
                        if(i > 0) {
 
1806
                                uchar line[30];
 
1807
 
 
1808
                                snprintf((char *) line, sizeof(line), "InputTCPMaxSessions %d", i);
 
1809
                                legacyOptsEnq(line);
 
1810
                        } else {
 
1811
                                if(ch == 't') {
 
1812
                                        fprintf(stderr, "rsyslogd: TCP session max configured "
 
1813
                                                "to %d [-t %s] - changing to 1.\n", i, arg);
 
1814
                                        legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
 
1815
                                } else if (ch == 'g') {
 
1816
                                        fprintf(stderr, "rsyslogd: GSS session max configured "
 
1817
                                                "to %d [-g %s] - changing to 1.\n", i, arg);
 
1818
                                        legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
 
1819
                                }
 
1820
                        }
 
1821
                }
 
1822
        } else
 
1823
                fprintf(stderr, "rsyslogd: Invalid -t %s command line option.\n", arg);
 
1824
}
 
1825
 
3558
1826
 
3559
1827
/* doDie() is a signal handler. If called, it sets the bFinished variable
3560
1828
 * to indicate the program should terminate. However, it does not terminate
3566
1834
 */
3567
1835
static void doDie(int sig)
3568
1836
{
3569
 
        dbgprintf("DoDie called.\n");
 
1837
        static int iRetries = 0; /* debug aid */
 
1838
        printf("DoDie called.\n");
 
1839
        if(iRetries++ == 4) {
 
1840
                printf("DoDie called 5 times - unconditional exit\n");
 
1841
                abort();
 
1842
        }
3570
1843
        bFinished = sig;
3571
1844
}
3572
1845
 
3573
1846
 
 
1847
/* This function frees all dynamically allocated memory for program termination.
 
1848
 * It must be called only immediately before exit(). It is primarily an aid
 
1849
 * for memory debuggers, which prevents cluttered outupt.
 
1850
 * rgerhards, 2008-03-20
 
1851
 */
 
1852
static void
 
1853
freeAllDynMemForTermination(void)
 
1854
{
 
1855
        if(pszWorkDir != NULL)
 
1856
                free(pszWorkDir);
 
1857
        if(pszMainMsgQFName != NULL)
 
1858
                free(pszMainMsgQFName);
 
1859
        if(pModDir != NULL)
 
1860
                free(pModDir);
 
1861
}
 
1862
 
 
1863
 
3574
1864
/* die() is called when the program shall end. This typically only occurs
3575
 
 * during sigterm or during the initialization. If you search for places where
3576
 
 * it is called, search for "die", not "die(", because the later will not find
3577
 
 * setting of signal handlers! As die() is intended to shutdown rsyslogd, it is
 
1865
 * during sigterm or during the initialization. 
 
1866
 * As die() is intended to shutdown rsyslogd, it is
3578
1867
 * safe to call exit() here. Just make sure that die() itself is not called
3579
1868
 * at inapropriate places. As a general rule of thumb, it is a bad idea to add
3580
1869
 * any calls to die() in new code!
3581
1870
 * rgerhards, 2005-10-24
3582
1871
 */
3583
 
static void die(int sig)
 
1872
static void
 
1873
die(int sig)
3584
1874
{
3585
1875
        char buf[256];
3586
 
        int i;
3587
 
 
 
1876
 
 
1877
        dbgprintf("exiting on signal %d\n", sig);
 
1878
 
 
1879
        /* IMPORTANT: we should close the inputs first, and THEN send our termination
 
1880
         * message. If we do it the other way around, logmsgInternal() may block on
 
1881
         * a full queue and the inputs still fill up that queue. Depending on the
 
1882
         * scheduling order, we may end up with logmsgInternal being held for a quite
 
1883
         * long time. When the inputs are terminated first, that should not happen
 
1884
         * because the queue is drained in parallel. The situation could only become
 
1885
         * an issue with extremely long running actions in a queue full environment.
 
1886
         * However, such actions are at least considered poorly written, if not
 
1887
         * outright wrong. So we do not care about this very remote problem.
 
1888
         * rgerhards, 2008-01-11
 
1889
         */
 
1890
 
 
1891
        /* close the inputs */
 
1892
        dbgprintf("Terminating input threads...\n");
 
1893
        thrdTerminateAll(); /* TODO: inputs only, please */
 
1894
 
 
1895
        /* and THEN send the termination log message (see long comment above) */
3588
1896
        if (sig) {
3589
 
                dbgprintf(" exiting on signal %d\n", sig);
3590
1897
                (void) snprintf(buf, sizeof(buf) / sizeof(char),
3591
1898
                 " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
3592
 
                 "\" x-pid=\"%d\"]" " exiting on signal %d.",
 
1899
                 "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
3593
1900
                 (int) myPid, sig);
3594
1901
                errno = 0;
3595
1902
                logmsgInternal(LOG_SYSLOG|LOG_INFO, buf, ADDDATE);
3596
1903
        }
3597
1904
        
3598
 
        /* Free ressources and close connections */
3599
 
        freeSelectors();
3600
 
 
3601
 
#ifdef  USE_PTHREADS
3602
 
        /* Worker threads are stopped by freeSelectors() */
3603
 
        queueDelete(pMsgQueue); /* delete fifo here! */
 
1905
        /* drain queue (if configured so) and stop main queue worker thread pool */
 
1906
        dbgprintf("Terminating main queue...\n");
 
1907
        queueDestruct(&pMsgQueue);
3604
1908
        pMsgQueue = NULL;
3605
 
#endif
3606
 
        
3607
 
        /* now clean up the listener part */
3608
 
#ifdef SYSLOG_INET
3609
 
        /* Close the UNIX sockets. */
3610
 
        for (i = 0; i < nfunix; i++)
3611
 
                if (funix[i] != -1)
3612
 
                        close(funix[i]);
3613
 
        /* Close the UDP inet socket. */
3614
 
        closeUDPListenSockets();
3615
 
        /* Close the TCP inet socket. */
3616
 
        if(sockTCPLstn != NULL && *sockTCPLstn) {
3617
 
                deinit_tcp_listener();
3618
 
        }
3619
 
#endif
3620
 
 
3621
 
        /* Clean-up files. */
3622
 
        for (i = 0; i < nfunix; i++)
3623
 
                if (funixn[i] && funix[i] != -1)
3624
 
                        (void)unlink(funixn[i]);
3625
 
 
 
1909
 
 
1910
        /* Free ressources and close connections. This includes flushing any remaining
 
1911
         * repeated msgs.
 
1912
         */
 
1913
        dbgprintf("Terminating outputs...\n");
 
1914
        freeSelectors();
 
1915
 
 
1916
        dbgprintf("all primary multi-thread sources have been terminated - now doing aux cleanup...\n");
3626
1917
        /* rger 2005-02-22
3627
1918
         * now clean up the in-memory structures. OK, the OS
3628
1919
         * would also take care of that, but if we do it
3638
1929
        /* de-init some modules */
3639
1930
        modExitIminternal();
3640
1931
 
 
1932
        /*dbgPrintAllDebugInfo(); / * this is the last spot where this can be done - below output modules are unloaded! */
 
1933
 
 
1934
        /* the following line cleans up CfSysLineHandlers that were not based on loadable
 
1935
         * modules. As such, they are not yet cleared.
 
1936
         */
3641
1937
        unregCfSysLineHdlrs();
3642
1938
 
 
1939
        legacyOptsFree();
 
1940
 
 
1941
        /* terminate the remaining classes */
 
1942
        GlobalClassExit();
 
1943
 
3643
1944
        /* TODO: this would also be the right place to de-init the builtin output modules. We
3644
1945
         * do not currently do that, because the module interface does not allow for
3645
1946
         * it. This will come some time later (it's essential with loadable modules).
3650
1951
         * init, so that modules are unloaded and reloaded on HUP to. Eventually it should go
3651
1952
         * into freeSelectors() - but that needs to be seen. -- rgerhards, 2007-08-09
3652
1953
         */
3653
 
        modUnloadAndDestructAll();
3654
 
 
3655
 
        /* clean up auxiliary data */
3656
 
        if(pModDir != NULL)
3657
 
                free(pModDir);
3658
 
 
3659
 
        dbgprintf("Clean shutdown completed, bye.\n");
 
1954
        module.UnloadAndDestructAll(eMOD_LINK_ALL);
 
1955
 
 
1956
        dbgprintf("Clean shutdown completed, bye\n");
 
1957
        /* dbgClassExit MUST be the last one, because it de-inits the debug system */
 
1958
        dbgClassExit();
 
1959
 
 
1960
        /* free all remaining memory blocks - this is not absolutely necessary, but helps
 
1961
         * us keep memory debugger logs clean and this is in aid in developing. It doesn't
 
1962
         * cost much time, so we do it always. -- rgerhards, 2008-03-20
 
1963
         */
 
1964
        freeAllDynMemForTermination();
 
1965
        /* NO CODE HERE - feeelAllDynMemForTermination() must be the last thing before exit()! */
3660
1966
        exit(0); /* "good" exit, this is the terminator function for rsyslog [die()] */
3661
1967
}
3662
1968
 
3671
1977
}
3672
1978
 
3673
1979
 
3674
 
/* parse an allowed sender config line and add the allowed senders
3675
 
 * (if the line is correct).
3676
 
 * rgerhards, 2005-09-27
3677
 
 */
3678
 
static rsRetVal addAllowedSenderLine(char* pName, uchar** ppRestOfConfLine)
3679
 
{
3680
 
#ifdef SYSLOG_INET
3681
 
        struct AllowedSenders **ppRoot;
3682
 
        struct AllowedSenders **ppLast;
3683
 
        rsParsObj *pPars;
3684
 
        rsRetVal iRet;
3685
 
        struct NetAddr *uIP = NULL;
3686
 
        int iBits;
3687
 
#endif
3688
 
 
3689
 
        assert(pName != NULL);
3690
 
        assert(ppRestOfConfLine != NULL);
3691
 
        assert(*ppRestOfConfLine != NULL);
3692
 
 
3693
 
#ifndef SYSLOG_INET
3694
 
        errno = 0;
3695
 
        logerror("config file contains allowed sender list, but rsyslogd "
3696
 
                 "compiled without Internet support - line ignored");
3697
 
        return RS_RET_ERR;
3698
 
#else
3699
 
        if(!strcasecmp(pName, "udp")) {
3700
 
                ppRoot = &pAllowedSenders_UDP;
3701
 
                ppLast = &pLastAllowedSenders_UDP;
3702
 
        } else if(!strcasecmp(pName, "tcp")) {
3703
 
                ppRoot = &pAllowedSenders_TCP;
3704
 
                ppLast = &pLastAllowedSenders_TCP;
3705
 
        } else {
3706
 
                logerrorSz("Invalid protocol '%s' in allowed sender "
3707
 
                           "list, line ignored", pName);
3708
 
                return RS_RET_ERR;
3709
 
        }
3710
 
 
3711
 
        /* OK, we now know the protocol and have valid list pointers.
3712
 
         * So let's process the entries. We are using the parse class
3713
 
         * for this.
3714
 
         */
3715
 
        /* create parser object starting with line string without leading colon */
3716
 
        if((iRet = rsParsConstructFromSz(&pPars, (uchar*) *ppRestOfConfLine) != RS_RET_OK)) {
3717
 
                logerrorInt("Error %d constructing parser object - ignoring allowed sender list", iRet);
3718
 
                return(iRet);
3719
 
        }
3720
 
 
3721
 
        while(!parsIsAtEndOfParseString(pPars)) {
3722
 
                if(parsPeekAtCharAtParsPtr(pPars) == '#')
3723
 
                        break; /* a comment-sign stops processing of line */
3724
 
                /* now parse a single IP address */
3725
 
                if((iRet = parsAddrWithBits(pPars, &uIP, &iBits)) != RS_RET_OK) {
3726
 
                        logerrorInt("Error %d parsing address in allowed sender"
3727
 
                                    "list - ignoring.", iRet);
3728
 
                        rsParsDestruct(pPars);
3729
 
                        return(iRet);
3730
 
                }
3731
 
                if((iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits))
3732
 
                        != RS_RET_OK) {
3733
 
                        logerrorInt("Error %d adding allowed sender entry "
3734
 
                                    "- ignoring.", iRet);
3735
 
                        rsParsDestruct(pPars);
3736
 
                        return(iRet);
3737
 
                }
3738
 
                free (uIP); /* copy stored in AllowedSenders list */ 
3739
 
        }
3740
 
 
3741
 
        /* cleanup */
3742
 
        *ppRestOfConfLine += parsGetCurrentPosition(pPars);
3743
 
        return rsParsDestruct(pPars);
3744
 
#endif /*#ifndef SYSLOG_INET */
3745
 
}
3746
 
 
3747
 
 
3748
 
/* process a directory and include all of its files into
3749
 
 * the current config file. There is no specific order of inclusion,
3750
 
 * files are included in the order they are read from the directory.
3751
 
 * The caller must have make sure that the provided parameter is
3752
 
 * indeed a directory.
3753
 
 * rgerhards, 2007-08-01
3754
 
 */
3755
 
static rsRetVal doIncludeDirectory(uchar *pDirName)
3756
 
{
3757
 
        DEFiRet;
3758
 
        int iEntriesDone = 0;
3759
 
        DIR *pDir;
3760
 
        union {
3761
 
              struct dirent d;
3762
 
              char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
3763
 
        } u;
3764
 
        struct dirent *res;
3765
 
        size_t iDirNameLen;
3766
 
        size_t iFileNameLen;
3767
 
        uchar szFullFileName[MAXFNAME];
3768
 
 
3769
 
        assert(pDirName != NULL);
3770
 
 
3771
 
        if((pDir = opendir((char*) pDirName)) == NULL) {
3772
 
                logerror("error opening include directory");
3773
 
                ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
3774
 
        }
3775
 
 
3776
 
        /* prepare file name buffer */
3777
 
        iDirNameLen = strlen((char*) pDirName);
3778
 
        memcpy(szFullFileName, pDirName, iDirNameLen);
3779
 
 
3780
 
        /* now read the directory */
3781
 
        iEntriesDone = 0;
3782
 
        while(readdir_r(pDir, &u.d, &res) == 0) {
3783
 
                if(res == NULL)
3784
 
                        break; /* this also indicates end of directory */
3785
 
                if(res->d_type != DT_REG)
3786
 
                        continue; /* we are not interested in special files */
3787
 
                if(res->d_name[0] == '.')
3788
 
                        continue; /* these files we are also not interested in */
3789
 
                ++iEntriesDone;
3790
 
                /* construct filename */
3791
 
                iFileNameLen = strnlen(res->d_name, NAME_MAX);
3792
 
                memcpy(szFullFileName + iDirNameLen, res->d_name, iFileNameLen);
3793
 
                *(szFullFileName + iDirNameLen + iFileNameLen) = '\0';
3794
 
                dbgprintf("including file '%s'\n", szFullFileName);
3795
 
                processConfFile(szFullFileName);
3796
 
                /* we deliberately ignore the iRet of processConfFile() - this is because
3797
 
                 * failure to process one file does not mean all files will fail. By ignoring,
3798
 
                 * we retry with the next file, which is the best thing we can do. -- rgerhards, 2007-08-01
3799
 
                 */
3800
 
        }
3801
 
 
3802
 
        if(iEntriesDone == 0) {
3803
 
                /* I just make it a debug output, because I can think of a lot of cases where it
3804
 
                 * makes sense not to have any files. E.g. a system maintainer may place a $Include
3805
 
                 * into the config file just in case, when additional modules be installed. When none
3806
 
                 * are installed, the directory will be empty, which is fine. -- rgerhards 2007-08-01
3807
 
                 */
3808
 
                dbgprintf("warning: the include directory contained no files - this may be ok.\n");
3809
 
        }
3810
 
 
3811
 
finalize_it:
3812
 
        if(pDir != NULL)
3813
 
                closedir(pDir);
3814
 
 
3815
 
        return iRet;
3816
 
}
3817
 
 
3818
 
 
3819
 
/* process a $include config line. That type of line requires
3820
 
 * inclusion of another file.
3821
 
 * rgerhards, 2007-08-01
3822
 
 */
3823
 
static rsRetVal doIncludeLine(uchar **pp, __attribute__((unused)) void* pVal)
3824
 
{
3825
 
        DEFiRet;
3826
 
        uchar cfgFile[MAXFNAME];
3827
 
 
3828
 
        assert(pp != NULL);
3829
 
        assert(*pp != NULL);
3830
 
 
3831
 
        if(getSubString(pp, (char*) cfgFile, sizeof(cfgFile) / sizeof(uchar), ' ')  != 0) {
3832
 
                logerror("could not extract group name");
3833
 
                ABORT_FINALIZE(RS_RET_NOT_FOUND);
3834
 
        }
3835
 
 
3836
 
        if(*(cfgFile+strlen((char*) cfgFile) - 1) == '/') {
3837
 
                dbgprintf("requested to include directory '%s'\n", cfgFile);
3838
 
                iRet = doIncludeDirectory(cfgFile);
3839
 
        } else {
3840
 
                dbgprintf("Requested to include config file '%s'\n", cfgFile);
3841
 
                iRet = processConfFile(cfgFile);
3842
 
        }
3843
 
 
3844
 
finalize_it:
3845
 
        return iRet;
3846
 
}
3847
 
 
3848
 
 
3849
 
/* process a $ModLoad config line.
3850
 
 * As of now, it is a dummy, that will later evolve into the
3851
 
 * loader for plug-ins.
3852
 
 * rgerhards, 2007-07-21
3853
 
 * varmojfekoj added support for dynamically loadable modules on 2007-08-13
3854
 
 * rgerhards, 2007-09-25: please note that the non-threadsafe function dlerror() is
3855
 
 * called below. This is ok because modules are currently only loaded during
3856
 
 * configuration file processing, which is executed on a single thread. Should we
3857
 
 * change that design at any stage (what is unlikely), we need to find a
3858
 
 * replacement.
3859
 
 */
3860
 
static rsRetVal doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
3861
 
{
3862
 
        DEFiRet;
3863
 
        uchar szName[512];
3864
 
        uchar szPath[512];
3865
 
        uchar errMsg[1024];
3866
 
        uchar *pModName;
3867
 
        void *pModHdlr, *pModInit;
3868
 
 
3869
 
        assert(pp != NULL);
3870
 
        assert(*pp != NULL);
3871
 
 
3872
 
        if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ')  != 0) {
3873
 
                logerror("could not extract module name");
3874
 
                ABORT_FINALIZE(RS_RET_NOT_FOUND);
3875
 
        }
3876
 
 
3877
 
        /* this below is a quick and dirty hack to provide compatibility with the
3878
 
         * $ModLoad MySQL forward compatibility statement. TODO: clean this up
3879
 
         * For the time being, it is clean enough, it just needs to be done
3880
 
         * differently when we have a full design for loadable plug-ins. For the
3881
 
         * time being, we just mangle the names a bit.
3882
 
         * rgerhards, 2007-08-14
3883
 
         */
3884
 
        if(!strcmp((char*) szName, "MySQL"))
3885
 
                pModName = (uchar*) "ommysql.so";
3886
 
        else
3887
 
                pModName = szName;
3888
 
 
3889
 
        dbgprintf("Requested to load module '%s'\n", szName);
3890
 
 
3891
 
        if(*pModName == '/') {
3892
 
                *szPath = '\0'; /* we do not need to append the path - its already in the module name */
3893
 
        } else {
3894
 
                strncpy((char *) szPath, (pModDir == NULL) ? _PATH_MODDIR : (char*) pModDir, sizeof(szPath));
3895
 
        }
3896
 
        strncat((char *) szPath, (char *) pModName, sizeof(szPath) - strlen((char*) szPath) - 1);
3897
 
        if(!(pModHdlr = dlopen((char *) szPath, RTLD_NOW))) {
3898
 
                snprintf((char *) errMsg, sizeof(errMsg), "could not load module '%s', dlopen: %s\n", szPath, dlerror());
3899
 
                errMsg[sizeof(errMsg)/sizeof(uchar) - 1] = '\0';
3900
 
                logerror((char *) errMsg);
3901
 
                ABORT_FINALIZE(RS_RET_ERR);
3902
 
        }
3903
 
        if(!(pModInit = dlsym(pModHdlr, "modInit"))) {
3904
 
                snprintf((char *) errMsg, sizeof(errMsg), "could not load module '%s', dlsym: %s\n", szPath, dlerror());
3905
 
                errMsg[sizeof(errMsg)/sizeof(uchar) - 1] = '\0';
3906
 
                logerror((char *) errMsg);
3907
 
                dlclose(pModHdlr);
3908
 
                ABORT_FINALIZE(RS_RET_ERR);
3909
 
        }
3910
 
        if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr)) != RS_RET_OK)
3911
 
                return iRet;
3912
 
 
3913
 
        skipWhiteSpace(pp); /* skip over any whitespace */
3914
 
 
3915
 
finalize_it:
3916
 
        return iRet;
3917
 
}
3918
 
 
3919
 
/* parse and interpret a $-config line that starts with
3920
 
 * a name (this is common code). It is parsed to the name
3921
 
 * and then the proper sub-function is called to handle
3922
 
 * the actual directive.
3923
 
 * rgerhards 2004-11-17
3924
 
 * rgerhards 2005-06-21: previously only for templates, now 
3925
 
 *    generalized.
3926
 
 */
3927
 
static rsRetVal doNameLine(uchar **pp, void* pVal)
3928
 
{
3929
 
        DEFiRet;
3930
 
        uchar *p;
3931
 
        enum eDirective eDir;
3932
 
        char szName[128];
3933
 
 
3934
 
        assert(pp != NULL);
3935
 
        p = *pp;
3936
 
        assert(p != NULL);
3937
 
 
3938
 
        eDir = (enum eDirective) pVal;  /* this time, it actually is NOT a pointer! */
3939
 
 
3940
 
        if(getSubString(&p, szName, sizeof(szName) / sizeof(char), ',')  != 0) {
3941
 
                logerror("Invalid config line: could not extract name - line ignored");
3942
 
                ABORT_FINALIZE(RS_RET_NOT_FOUND);
3943
 
        }
3944
 
        if(*p == ',')
3945
 
                ++p; /* comma was eaten */
3946
 
        
3947
 
        /* we got the name - now we pass name & the rest of the string
3948
 
         * to the subfunction. It makes no sense to do further
3949
 
         * parsing here, as this is in close interaction with the
3950
 
         * respective subsystem. rgerhards 2004-11-17
3951
 
         */
3952
 
        
3953
 
        switch(eDir) {
3954
 
                case DIR_TEMPLATE: 
3955
 
                        tplAddLine(szName, &p);
3956
 
                        break;
3957
 
                case DIR_OUTCHANNEL: 
3958
 
                        ochAddLine(szName, &p);
3959
 
                        break;
3960
 
                case DIR_ALLOWEDSENDER: 
3961
 
                        addAllowedSenderLine(szName, &p);
3962
 
                        break;
3963
 
                default:/* we do this to avoid compiler warning - not all
3964
 
                         * enum values call this function, so an incomplete list
3965
 
                         * is quite ok (but then we should not run into this code,
3966
 
                         * so at least we log a debug warning).
3967
 
                         */
3968
 
                        dbgprintf("INTERNAL ERROR: doNameLine() called with invalid eDir %d.\n",
3969
 
                                eDir);
3970
 
                        break;
3971
 
        }
3972
 
 
3973
 
        *pp = p;
3974
 
 
3975
 
finalize_it:
3976
 
        return iRet;
3977
 
}
3978
 
 
3979
 
 
3980
1980
/* set the action resume interval
3981
1981
 */
3982
1982
static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
3996
1996
}
3997
1997
 
3998
1998
 
3999
 
/* Parse and interpret a system-directive in the config line
4000
 
 * A system directive is one that starts with a "$" sign. It offers
4001
 
 * extended configuration parameters.
4002
 
 * 2004-11-17 rgerhards
4003
 
 */
4004
 
rsRetVal cfsysline(uchar *p)
4005
 
{
4006
 
        DEFiRet;
4007
 
        uchar szCmd[64];
4008
 
        uchar errMsg[128];      /* for dynamic error messages */
4009
 
 
4010
 
        assert(p != NULL);
4011
 
        errno = 0;
4012
 
        if(getSubString(&p, (char*) szCmd, sizeof(szCmd) / sizeof(uchar), ' ')  != 0) {
4013
 
                logerror("Invalid $-configline - could not extract command - line ignored\n");
4014
 
                ABORT_FINALIZE(RS_RET_NOT_FOUND);
4015
 
        }
4016
 
 
4017
 
        /* we now try and see if we can find the command in the registered
4018
 
         * list of cfsysline handlers. -- rgerhards, 2007-07-31
4019
 
         */
4020
 
        CHKiRet(processCfSysLineCommand(szCmd, &p));
4021
 
 
4022
 
        /* now check if we have some extra characters left on the line - that
4023
 
         * should not be the case. Whitespace is OK, but everything else should
4024
 
         * trigger a warning (that may be an indication of undesired behaviour).
4025
 
         * An exception, of course, are comments (starting with '#').
4026
 
         * rgerhards, 2007-07-04
4027
 
         */
4028
 
        skipWhiteSpace(&p);
4029
 
 
4030
 
        if(*p && *p != '#') { /* we have a non-whitespace, so let's complain */
4031
 
                snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
4032
 
                         "error: extra characters in config line ignored: '%s'", p);
4033
 
                errno = 0;
4034
 
                logerror((char*) errMsg);
4035
 
        }
4036
 
 
4037
 
finalize_it:
4038
 
        return iRet;
4039
 
}
4040
 
 
4041
 
 
4042
1999
/* helper to freeSelectors(), used with llExecFunc() to flush 
4043
2000
 * pending output.  -- rgerhards, 2007-08-02
 
2001
 * We do not need to lock the action object here as the processing
 
2002
 * queue is already empty and no other threads are running when
 
2003
 * we call this function. -- rgerhards, 2007-12-12
4044
2004
 */
4045
2005
DEFFUNC_llExecFunc(freeSelectorsActions)
4046
2006
{
4050
2010
 
4051
2011
        /* flush any pending output */
4052
2012
        if(pAction->f_prevcount) {
4053
 
                fprintlog(pAction);
 
2013
                actionWriteToAction(pAction);
4054
2014
        }
4055
2015
 
4056
2016
        return RS_RET_OK; /* never fails ;) */
4067
2027
        if(Files != NULL) {
4068
2028
                dbgprintf("Freeing log structures.\n");
4069
2029
 
4070
 
                /* just in case, we flush the emergency log. If error messages occur after
4071
 
                 * this stage, we loose them, but that's ok. With multi-threading, this can
4072
 
                 * never happen.  -- rgerhards, 2007-08-03
4073
 
                 */
4074
 
                processImInternal();
4075
 
 
4076
 
                /* we need first to flush, then wait for all messages to be processed
4077
 
                 * (stopWoker() does that), then we can free the structures.
4078
 
                 */
4079
2030
                for(f = Files ; f != NULL ; f = f->f_next) {
4080
2031
                        llExecFunc(&f->llActList, freeSelectorsActions, NULL);
4081
2032
                }
4082
2033
 
4083
 
#               ifdef USE_PTHREADS
4084
 
                stopWorker();
4085
 
#               endif
4086
 
 
 
2034
                /* actions flushed and ready for destruction - so do that... */
4087
2035
                f = Files;
4088
2036
                while (f != NULL) {
4089
2037
                        fPrev = f;
4093
2041
 
4094
2042
                /* Reflect the deletion of the selectors linked list. */
4095
2043
                Files = NULL;
4096
 
                Initialized = 0;
 
2044
                bHaveMainQueue = 0;
4097
2045
        }
4098
2046
}
4099
2047
 
4106
2054
{
4107
2055
        DEFiRet;
4108
2056
        iRet = actionDbgPrint((action_t*) pData);
4109
 
        printf("\n");
 
2057
        dbgprintf("\n");
4110
2058
 
4111
 
        return iRet;
 
2059
        RETiRet;
4112
2060
}
4113
2061
 
4114
2062
/* print debug information as part of init(). This pretty much
4122
2070
        int iSelNbr = 1;
4123
2071
        int i;
4124
2072
 
4125
 
        printf("\nActive selectors:\n");
 
2073
        dbgprintf("\nActive selectors:\n");
4126
2074
        for (f = Files; f != NULL ; f = f->f_next) {
4127
 
                printf("Selector %d:\n", iSelNbr++);
 
2075
                dbgprintf("Selector %d:\n", iSelNbr++);
4128
2076
                if(f->pCSProgNameComp != NULL)
4129
 
                        printf("tag: '%s'\n", rsCStrGetSzStrNoNULL(f->pCSProgNameComp));
 
2077
                        dbgprintf("tag: '%s'\n", rsCStrGetSzStrNoNULL(f->pCSProgNameComp));
4130
2078
                if(f->eHostnameCmpMode != HN_NO_COMP)
4131
 
                        printf("hostname: %s '%s'\n",
 
2079
                        dbgprintf("hostname: %s '%s'\n",
4132
2080
                                f->eHostnameCmpMode == HN_COMP_MATCH ?
4133
2081
                                        "only" : "allbut",
4134
2082
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp));
4135
2083
                if(f->f_filter_type == FILTER_PRI) {
4136
2084
                        for (i = 0; i <= LOG_NFACILITIES; i++)
4137
2085
                                if (f->f_filterData.f_pmask[i] == TABLE_NOPRI)
4138
 
                                        printf(" X ");
 
2086
                                        dbgprintf(" X ");
4139
2087
                                else
4140
 
                                        printf("%2X ", f->f_filterData.f_pmask[i]);
 
2088
                                        dbgprintf("%2X ", f->f_filterData.f_pmask[i]);
 
2089
                } else if(f->f_filter_type == FILTER_EXPR) {
 
2090
                        dbgprintf("EXPRESSION-BASED Filter: can currently not be displayed");
4141
2091
                } else {
4142
 
                        printf("PROPERTY-BASED Filter:\n");
4143
 
                        printf("\tProperty.: '%s'\n",
 
2092
                        dbgprintf("PROPERTY-BASED Filter:\n");
 
2093
                        dbgprintf("\tProperty.: '%s'\n",
4144
2094
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName));
4145
 
                        printf("\tOperation: ");
 
2095
                        dbgprintf("\tOperation: ");
4146
2096
                        if(f->f_filterData.prop.isNegated)
4147
 
                                printf("NOT ");
4148
 
                        printf("'%s'\n", getFIOPName(f->f_filterData.prop.operation));
4149
 
                        printf("\tValue....: '%s'\n",
 
2097
                                dbgprintf("NOT ");
 
2098
                        dbgprintf("'%s'\n", getFIOPName(f->f_filterData.prop.operation));
 
2099
                        dbgprintf("\tValue....: '%s'\n",
4150
2100
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue));
4151
 
                        printf("\tAction...: ");
 
2101
                        dbgprintf("\tAction...: ");
4152
2102
                }
4153
2103
 
4154
 
                printf("\nActions:\n");
 
2104
                dbgprintf("\nActions:\n");
4155
2105
                llExecFunc(&f->llActList, dbgPrintInitInfoAction, NULL); /* actions */
4156
2106
 
4157
 
                printf("\n");
 
2107
                dbgprintf("\n");
4158
2108
        }
4159
 
        printf("\n");
 
2109
        dbgprintf("\n");
4160
2110
        if(bDebugPrintTemplateList)
4161
2111
                tplPrintList();
4162
2112
        if(bDebugPrintModuleList)
4163
 
                modPrintList();
 
2113
                module.PrintList();
4164
2114
        ochPrintList();
4165
2115
 
4166
2116
        if(bDebugPrintCfSysLineHandlerList)
4167
2117
                dbgPrintCfSysLineHandlers();
4168
2118
 
4169
 
#ifdef  SYSLOG_INET
4170
 
        /* now the allowedSender lists: */
4171
 
        PrintAllowedSenders(1); /* UDP */
4172
 
        PrintAllowedSenders(2); /* TCP */
4173
 
        printf("\n");
4174
 
#endif  /* #ifdef SYSLOG_INET */
4175
 
 
4176
 
        printf("Messages with malicious PTR DNS Records are %sdropped.\n",
 
2119
        dbgprintf("Messages with malicious PTR DNS Records are %sdropped.\n",
4177
2120
                bDropMalPTRMsgs ? "" : "not ");
4178
2121
 
4179
 
        printf("Control characters are %sreplaced upon reception.\n",
 
2122
        dbgprintf("Control characters are %sreplaced upon reception.\n",
4180
2123
                        bEscapeCCOnRcv? "" : "not ");
4181
2124
 
4182
2125
        if(bEscapeCCOnRcv)
4183
 
                printf("Control character escape sequence prefix is '%c'.\n",
 
2126
                dbgprintf("Control character escape sequence prefix is '%c'.\n",
4184
2127
                        cCCEscapeChar);
4185
2128
 
4186
 
#ifdef  USE_PTHREADS
4187
 
        printf("Main queue size %d messages.\n", iMainMsgQueueSize);
4188
 
#endif
 
2129
        dbgprintf("Main queue size %d messages.\n", iMainMsgQueueSize);
 
2130
        dbgprintf("Main queue worker threads: %d, Perists every %d updates.\n",
 
2131
                  iMainMsgQueueNumWorkers, iMainMsgQPersistUpdCnt);
 
2132
        dbgprintf("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n",
 
2133
                   iMainMsgQtoQShutdown, iMainMsgQtoActShutdown, iMainMsgQtoEnq);
 
2134
        dbgprintf("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d\n",
 
2135
                   iMainMsgQHighWtrMark, iMainMsgQLowWtrMark, iMainMsgQDiscardMark, iMainMsgQDiscardSeverity);
 
2136
        dbgprintf("Main queue save on shutdown %d, max disk space allowed %lld\n",
 
2137
                   bMainMsgQSaveOnShutdown, iMainMsgQueMaxDiskSpace);
 
2138
        /* TODO: add
 
2139
        iActionRetryCount = 0;
 
2140
        iActionRetryInterval = 30000;
 
2141
        static int iMainMsgQtoWrkShutdown = 60000;
 
2142
        static int iMainMsgQtoWrkMinMsgs = 100; 
 
2143
        static int iMainMsgQbSaveOnShutdown = 1;
 
2144
        iMainMsgQueMaxDiskSpace = 0;
 
2145
        setQPROP(queueSettoWrkShutdown, "$MainMsgQueueTimeoutWorkerThreadShutdown", 5000);
 
2146
        setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
 
2147
        setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
 
2148
         */
 
2149
        dbgprintf("Work Directory: '%s'.\n", pszWorkDir);
4189
2150
}
4190
2151
 
4191
2152
 
4192
 
/* process a configuration file
4193
 
 * started with code from init() by rgerhards on 2007-07-31
 
2153
/* Start the input modules. This function will probably undergo big changes
 
2154
 * while we implement the input module interface. For now, it does the most
 
2155
 * important thing to get at least my poor initial input modules up and
 
2156
 * running. Almost no config option is taken.
 
2157
 * rgerhards, 2007-12-14
4194
2158
 */
4195
 
static rsRetVal processConfFile(uchar *pConfFile)
 
2159
static rsRetVal
 
2160
startInputModules(void)
4196
2161
{
4197
2162
        DEFiRet;
4198
 
        int iLnNbr = 0;
4199
 
        FILE *cf;
4200
 
        selector_t *fCurr = NULL;
4201
 
        uchar *p;
4202
 
#ifdef CONT_LINE
4203
 
        uchar cbuf[BUFSIZ];
4204
 
        uchar *cline;
4205
 
#else
4206
 
        uchar cline[BUFSIZ];
4207
 
#endif
4208
 
        assert(pConfFile != NULL);
4209
 
 
4210
 
        if((cf = fopen((char*)pConfFile, "r")) == NULL) {
4211
 
                ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
4212
 
        }
4213
 
 
4214
 
        /* Now process the file.
4215
 
         */
4216
 
#if CONT_LINE
4217
 
        cline = cbuf;
4218
 
        while (fgets((char*)cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
4219
 
#else
4220
 
        while (fgets(cline, sizeof(cline), cf) != NULL) {
4221
 
#endif
4222
 
                ++iLnNbr;
4223
 
                /* drop LF - TODO: make it better, replace fgets(), but its clean as it is */
4224
 
                if(cline[strlen((char*)cline)-1] == '\n') {
4225
 
                        cline[strlen((char*)cline) -1] = '\0';
4226
 
                }
4227
 
                /* check for end-of-section, comments, strip off trailing
4228
 
                 * spaces and newline character.
4229
 
                 */
4230
 
                p = cline;
4231
 
                skipWhiteSpace(&p);
4232
 
                if (*p == '\0' || *p == '#')
4233
 
                        continue;
4234
 
 
4235
 
#if CONT_LINE
4236
 
                strcpy((char*)cline, (char*)p);
4237
 
#endif
4238
 
                for (p = (uchar*) strchr((char*)cline, '\0'); isspace((int) *--p););
4239
 
#if CONT_LINE
4240
 
                if (*p == '\\') {
4241
 
                        if ((p - cbuf) > BUFSIZ - 30) {
4242
 
                                /* Oops the buffer is full - what now? */
4243
 
                                cline = cbuf;
4244
 
                        } else {
4245
 
                                *p = 0;
4246
 
                                cline = p;
4247
 
                                continue;
4248
 
                        }
4249
 
                }  else
4250
 
                        cline = cbuf;
4251
 
#endif
4252
 
                *++p = '\0'; // TODO: check this
4253
 
 
4254
 
                /* we now have the complete line, and are positioned at the first non-whitespace
4255
 
                 * character. So let's process it
4256
 
                 */
4257
 
#if CONT_LINE
4258
 
                if(cfline(cbuf, &fCurr) != RS_RET_OK) {
4259
 
#else
4260
 
                if(cfline((uchar*)cline, &fCurr) != RS_RET_OK) {
4261
 
#endif
4262
 
                        /* we log a message, but otherwise ignore the error. After all, the next
4263
 
                         * line can be correct.  -- rgerhards, 2007-08-02
4264
 
                         */
4265
 
                        uchar szErrLoc[MAXFNAME + 64];
4266
 
                        dbgprintf("config line NOT successfully processed\n");
4267
 
                        snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
4268
 
                                 "%s, line %d", pConfFile, iLnNbr);
4269
 
                        logerrorSz("the last error occured in %s", (char*)szErrLoc);
4270
 
                }
4271
 
        }
4272
 
 
4273
 
        /* we probably have one selector left to be added - so let's do that now */
4274
 
        CHKiRet(selectorAddList(fCurr));
4275
 
 
4276
 
        /* close the configuration file */
4277
 
        (void) fclose(cf);
4278
 
 
4279
 
finalize_it:
4280
 
        if(iRet != RS_RET_OK) {
4281
 
                char errStr[1024];
4282
 
                if(fCurr != NULL)
4283
 
                        selectorDestruct(fCurr);
4284
 
                dbgprintf("error %d processing config file '%s'; os error (if any): %s\n",
4285
 
                        iRet, pConfFile, strerror_r(errno, errStr, sizeof(errStr)));
4286
 
        }
4287
 
        return iRet;
 
2163
        modInfo_t *pMod;
 
2164
 
 
2165
        /* loop through all modules and activate them (brr...) */
 
2166
        pMod = module.GetNxtType(NULL, eMOD_IN);
 
2167
        while(pMod != NULL) {
 
2168
                if((iRet = pMod->mod.im.willRun()) == RS_RET_OK) {
 
2169
                        /* activate here */
 
2170
                        thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun);
 
2171
                } else {
 
2172
                        dbgprintf("module %lx will not run, iRet %d\n", (unsigned long) pMod, iRet);
 
2173
                }
 
2174
        pMod = module.GetNxtType(pMod, eMOD_IN);
 
2175
        }
 
2176
 
 
2177
        ENDfunc
 
2178
        return RS_RET_OK; /* intentional: we do not care about module errors */
4288
2179
}
4289
2180
 
4290
2181
 
4291
2182
/* INIT -- Initialize syslogd from configuration table
4292
2183
 * init() is called at initial startup AND each time syslogd is HUPed
4293
2184
 */
4294
 
static void init(void)
 
2185
static void
 
2186
init(void)
4295
2187
{
4296
2188
        DEFiRet;
4297
 
        register int i;
4298
 
#ifdef CONT_LINE
4299
2189
        char cbuf[BUFSIZ];
4300
 
#else
4301
 
        char cline[BUFSIZ];
4302
 
#endif
4303
2190
        char bufStartUpMsg[512];
4304
 
        struct servent *sp;
4305
2191
        struct sigaction sigAct;
4306
2192
 
 
2193
        thrdTerminateAll(); /* stop all running input threads - TODO: reconsider location! */
 
2194
 
4307
2195
        /* initialize some static variables */
4308
2196
        pDfltHostnameCmp = NULL;
4309
2197
        pDfltProgNameCmp = NULL;
4310
2198
        eDfltHostnameCmpMode = HN_NO_COMP;
4311
 
        Forwarding = 0;
4312
 
 
4313
 
#ifdef SYSLOG_INET
4314
 
        if (restart) {
4315
 
                if (pAllowedSenders_UDP != NULL) {
4316
 
                        clearAllowedSenders (pAllowedSenders_UDP);
4317
 
                        pAllowedSenders_UDP = NULL;
4318
 
                }
4319
 
                
4320
 
                if (pAllowedSenders_TCP != NULL) {
4321
 
                        clearAllowedSenders (pAllowedSenders_TCP);
4322
 
                        pAllowedSenders_TCP = NULL;
4323
 
                }
4324
 
        }
4325
 
 
4326
 
        assert (pAllowedSenders_UDP == NULL &&
4327
 
                pAllowedSenders_TCP == NULL );
4328
 
#endif
4329
 
        /* I was told by an IPv6 expert that calling getservbyname() seems to be
4330
 
         * still valid, at least for the use case we have. So I re-enabled that
4331
 
         * code. rgerhards, 2007-07-02
4332
 
         */
4333
 
        if(!strcmp(LogPort, "0")) {
4334
 
                /* we shall use the default syslog/udp port, so let's
4335
 
                 * look it up.
4336
 
                 * NOTE: getservbyname() is not thread-safe, but this is OK as 
4337
 
                 * it is called only during init, in single-threading mode.
4338
 
                 */
4339
 
                sp = getservbyname("syslog", "udp");
4340
 
                if (sp == NULL) {
4341
 
                        errno = 0;
4342
 
                        logerror("Could not find syslog/udp port in /etc/services. "
4343
 
                                 "Now using IANA-assigned default of 514.");
4344
 
                        LogPort = "514";
4345
 
                } else {
4346
 
                        /* we can dynamically allocate memory here and do NOT need
4347
 
                         * to care about freeing it because even though init() is
4348
 
                         * called on each restart, the LogPort can never again be
4349
 
                         * "0". So we will only once run into this part of the code
4350
 
                         * here. rgerhards, 2007-07-02
4351
 
                         * We save ourselfs the hassle of dynamic memory management
4352
 
                         * for the very same reason.
4353
 
                         */
4354
 
                        static char defPort[8];
4355
 
                        snprintf(defPort, sizeof(defPort), "%d", ntohs(sp->s_port));
4356
 
                        LogPort = defPort;
4357
 
                }
4358
 
        }
4359
2199
 
4360
2200
        dbgprintf("rsyslog %s.\n", VERSION);
4361
2201
        dbgprintf("Called init.\n");
4362
2202
 
4363
 
        /*  Close all open log files and free log descriptor array. */
 
2203
        /* delete the message queue, which also flushes all messages left over */
 
2204
        if(pMsgQueue != NULL) {
 
2205
                dbgprintf("deleting main message queue\n");
 
2206
                queueDestruct(&pMsgQueue); /* delete pThis here! */
 
2207
                pMsgQueue = NULL;
 
2208
        }
 
2209
 
 
2210
        /*  Close all open log files and free log descriptor array. This also frees
 
2211
         *  all output-modules instance data.
 
2212
         */
4364
2213
        freeSelectors();
4365
2214
 
4366
2215
        /* Unload all non-static modules */
4367
2216
        dbgprintf("Unloading non-static modules.\n");
4368
 
        modUnloadAndDestructDynamic();
 
2217
        module.UnloadAndDestructAll(eMOD_LINK_DYNAMIC_LOADED);
4369
2218
 
4370
2219
        dbgprintf("Clearing templates.\n");
4371
2220
        tplDeleteNew();
4372
2221
 
4373
 
#ifdef  USE_PTHREADS
4374
 
        if(pMsgQueue != NULL) {
4375
 
                dbgprintf("deleting message queue\n");
4376
 
                queueDelete(pMsgQueue); /* delete fifo here! */
4377
 
                pMsgQueue = NULL;
4378
 
        }
4379
 
#endif
4380
 
        
4381
2222
        /* re-setting values to defaults (where applicable) */
4382
2223
        /* TODO: once we have loadable modules, we must re-visit this code. The reason is
4383
2224
         * that config variables are not re-set, because the module is not yet loaded. On
4386
2227
         * think about the whole situation when we implement loadable plugins.
4387
2228
         * rgerhards, 2007-07-31
4388
2229
         */
4389
 
        cfsysline((uchar*)"ResetConfigVariables");
 
2230
        conf.cfsysline((uchar*)"ResetConfigVariables");
4390
2231
 
4391
2232
        /* open the configuration file */
4392
 
        if((iRet = processConfFile(ConfFile)) != RS_RET_OK) {
 
2233
        if((iRet = conf.processConfFile(ConfFile)) != RS_RET_OK) {
4393
2234
                /* rgerhards: this code is executed to set defaults when the
4394
2235
                 * config file could not be opened. We might think about
4395
2236
                 * abandoning the run in this case - but this, too, is not
4397
2238
                 * We ignore any errors while doing this - we would be lost anyhow...
4398
2239
                 */
4399
2240
                selector_t *f = NULL;
4400
 
                char szTTYNameBuf[TTY_NAME_MAX+1]; /* +1 for NULL character */
 
2241
                char szTTYNameBuf[_POSIX_TTY_NAME_MAX+1]; /* +1 for NULL character */
4401
2242
                dbgprintf("primary config file could not be opened - using emergency definitions.\n");
4402
 
                cfline((uchar*)"*.ERR\t" _PATH_CONSOLE, &f);
4403
 
                cfline((uchar*)"*.PANIC\t*", &f);
 
2243
                conf.cfline((uchar*)"*.ERR\t" _PATH_CONSOLE, &f);
 
2244
                conf.cfline((uchar*)"*.PANIC\t*", &f);
4404
2245
                if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
4405
2246
                        snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
4406
 
                        cfline((uchar*)cbuf, &f);
 
2247
                        conf.cfline((uchar*)cbuf, &f);
4407
2248
                }
4408
2249
                selectorAddList(f);
4409
2250
        }
4410
2251
 
 
2252
        legacyOptsHook();
 
2253
 
4411
2254
        /* we are now done with reading the configuration. This is the right time to
4412
2255
         * free some objects that were just needed for loading it. rgerhards 2005-10-19
4413
2256
         */
4414
2257
        if(pDfltHostnameCmp != NULL) {
4415
 
                rsCStrDestruct(pDfltHostnameCmp);
4416
 
                pDfltHostnameCmp = NULL;
 
2258
                rsCStrDestruct(&pDfltHostnameCmp);
4417
2259
        }
4418
2260
 
4419
2261
        if(pDfltProgNameCmp != NULL) {
4420
 
                rsCStrDestruct(pDfltProgNameCmp);
4421
 
                pDfltProgNameCmp = NULL;
4422
 
        }
4423
 
 
4424
 
#ifdef SYSLOG_UNIXAF
4425
 
        for (i = startIndexUxLocalSockets ; i < nfunix ; i++) {
4426
 
                if (funix[i] != -1)
4427
 
                        /* Don't close the socket, preserve it instead
4428
 
                        close(funix[i]);
4429
 
                        */
4430
 
                        continue;
4431
 
                if ((funix[i] = create_unix_socket(funixn[i])) != -1)
4432
 
                        dbgprintf("Opened UNIX socket `%s' (fd %d).\n", funixn[i], funix[i]);
4433
 
        }
4434
 
#endif
4435
 
 
4436
 
#ifdef SYSLOG_INET
4437
 
        /* I have moved initializing UDP sockets before the TCP sockets. This ensures
4438
 
         * they are as soon ready for reception as possible. Of course, it is only a 
4439
 
         * very small window of exposure, but it doesn't hurt to limit the message
4440
 
         * loss risk to as low as possible - especially if it costs nothing...
4441
 
         * rgerhards, 2007-06-28
4442
 
         */
4443
 
        if(Forwarding || AcceptRemote) {
4444
 
                if (finet == NULL) {
4445
 
                        if((finet = create_udp_socket()) != NULL)
4446
 
                                dbgprintf("Opened %d syslog UDP port(s).\n", *finet);
4447
 
                }
4448
 
        } else {
4449
 
                /* this case can happen during HUP processing. */
4450
 
                closeUDPListenSockets();
4451
 
        }
4452
 
 
4453
 
        if (bEnableTCP) {
4454
 
                if(sockTCPLstn == NULL) {
4455
 
                        /* even when doing a re-init, we do not shut down and
4456
 
                         * re-open the TCP socket. That would break existing TCP
4457
 
                         * session, which we do not desire. Should at some time arise
4458
 
                         * need to do that, I recommend controlling that via a
4459
 
                         * user-selectable option. rgerhards, 2007-06-21
4460
 
                         */
4461
 
                        if((sockTCPLstn = create_tcp_socket()) != NULL) {
4462
 
                                dbgprintf("Opened %d syslog TCP port(s).\n", *sockTCPLstn);
4463
 
                        }
4464
 
                }
4465
 
        }
4466
 
#endif
4467
 
 
4468
 
#       ifdef USE_PTHREADS
 
2262
                rsCStrDestruct(&pDfltProgNameCmp);
 
2263
        }
 
2264
 
 
2265
        /* some checks */
 
2266
        if(iMainMsgQueueNumWorkers < 1) {
 
2267
                errmsg.LogError(NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n");
 
2268
                iMainMsgQueueNumWorkers = 1;
 
2269
        }
 
2270
 
 
2271
        if(MainMsgQueType == QUEUETYPE_DISK) {
 
2272
                errno = 0;      /* for logerror! */
 
2273
                if(pszWorkDir == NULL) {
 
2274
                        errmsg.LogError(NO_ERRCODE, "No $WorkDirectory specified - can not run main message queue in 'disk' mode. "
 
2275
                                 "Using 'FixedArray' instead.\n");
 
2276
                        MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
 
2277
                }
 
2278
                if(pszMainMsgQFName == NULL) {
 
2279
                        errmsg.LogError(NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main message queue in "
 
2280
                                 "'disk' mode. Using 'FixedArray' instead.\n");
 
2281
                        MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
 
2282
                }
 
2283
        }
 
2284
 
 
2285
        /* switch the message object to threaded operation, if necessary */
 
2286
        if(MainMsgQueType == QUEUETYPE_DIRECT || iMainMsgQueueNumWorkers > 1) {
 
2287
                MsgEnableThreadSafety();
 
2288
        }
 
2289
 
4469
2290
        /* create message queue */
4470
 
        pMsgQueue = queueInit();
4471
 
        if(pMsgQueue == NULL) {
4472
 
                errno = 0;
4473
 
                logerror("error: could not create message queue - running single-threaded!\n");
4474
 
        }
4475
 
 
4476
 
        startWorker();
4477
 
#       endif
4478
 
 
4479
 
        Initialized = 1;
 
2291
        CHKiRet_Hdlr(queueConstruct(&pMsgQueue, MainMsgQueType, iMainMsgQueueNumWorkers, iMainMsgQueueSize, msgConsumer)) {
 
2292
                /* no queue is fatal, we need to give up in that case... */
 
2293
                fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
 
2294
                exit(1);
 
2295
        }
 
2296
        /* name our main queue object (it's not fatal if it fails...) */
 
2297
        obj.SetName((obj_t*) pMsgQueue, (uchar*) "main queue");
 
2298
 
 
2299
        /* ... set some properties ... */
 
2300
#       define setQPROP(func, directive, data) \
 
2301
        CHKiRet_Hdlr(func(pMsgQueue, data)) { \
 
2302
                errmsg.LogError(NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
 
2303
        }
 
2304
#       define setQPROPstr(func, directive, data) \
 
2305
        CHKiRet_Hdlr(func(pMsgQueue, data, (data == NULL)? 0 : strlen((char*) data))) { \
 
2306
                errmsg.LogError(NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
 
2307
        }
 
2308
 
 
2309
        setQPROP(queueSetMaxFileSize, "$MainMsgQueueFileSize", iMainMsgQueMaxFileSize);
 
2310
        setQPROP(queueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", iMainMsgQueMaxDiskSpace);
 
2311
        setQPROPstr(queueSetFilePrefix, "$MainMsgQueueFileName", pszMainMsgQFName);
 
2312
        setQPROP(queueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", iMainMsgQPersistUpdCnt);
 
2313
        setQPROP(queueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", iMainMsgQtoQShutdown );
 
2314
        setQPROP(queueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion", iMainMsgQtoActShutdown);
 
2315
        setQPROP(queueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown", iMainMsgQtoWrkShutdown);
 
2316
        setQPROP(queueSettoEnq, "$MainMsgQueueTimeoutEnqueue", iMainMsgQtoEnq);
 
2317
        setQPROP(queueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark", iMainMsgQHighWtrMark);
 
2318
        setQPROP(queueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark", iMainMsgQLowWtrMark);
 
2319
        setQPROP(queueSetiDiscardMrk, "$MainMsgQueueDiscardMark", iMainMsgQDiscardMark);
 
2320
        setQPROP(queueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity", iMainMsgQDiscardSeverity);
 
2321
        setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", iMainMsgQWrkMinMsgs);
 
2322
        setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", bMainMsgQSaveOnShutdown);
 
2323
        setQPROP(queueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", iMainMsgQDeqSlowdown);
 
2324
 
 
2325
#       undef setQPROP
 
2326
#       undef setQPROPstr
 
2327
 
 
2328
        /* ... and finally start the queue! */
 
2329
        CHKiRet_Hdlr(queueStart(pMsgQueue)) {
 
2330
                /* no queue is fatal, we need to give up in that case... */
 
2331
                fprintf(stderr, "fatal error %d: could not start message queue - rsyslogd can not run!\n", iRet);
 
2332
                exit(1);
 
2333
        }
 
2334
 
 
2335
        bHaveMainQueue = (MainMsgQueType == QUEUETYPE_DIRECT) ? 0 : 1;
 
2336
        dbgprintf("Main processing queue is initialized and running\n");
 
2337
 
 
2338
        /* the output part and the queue is now ready to run. So it is a good time
 
2339
         * to start the inputs. Please note that the net code above should be
 
2340
         * shuffled to down here once we have everything in input modules.
 
2341
         * rgerhards, 2007-12-14
 
2342
         */
 
2343
        startInputModules();
4480
2344
 
4481
2345
        if(Debug) {
4482
2346
                dbgPrintInitInfo();
4487
2351
         */
4488
2352
        snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char), 
4489
2353
                 " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
4490
 
                 "\" x-pid=\"%d\"][x-configInfo udpReception=\"%s\" " \
4491
 
                 "udpPort=\"%s\" tcpReception=\"%s\" tcpPort=\"%s\"]" \
4492
 
                 " restart",
4493
 
                 (int) myPid,
4494
 
#ifdef  SYSLOG_INET
4495
 
                 AcceptRemote ? "Yes" : "No", LogPort,
4496
 
                 bEnableTCP   ? "Yes" : "No", TCPLstnPort
4497
 
#else
4498
 
                "No", "0", "No", "0"
4499
 
#endif  /* #ifdef SYSLOG_INET */
4500
 
                );
 
2354
                 "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] restart",
 
2355
                 (int) myPid);
4501
2356
        logmsgInternal(LOG_SYSLOG|LOG_INFO, bufStartUpMsg, ADDDATE);
4502
2357
 
4503
2358
        memset(&sigAct, 0, sizeof (sigAct));
4505
2360
        sigAct.sa_handler = sighup_handler;
4506
2361
        sigaction(SIGHUP, &sigAct, NULL);
4507
2362
 
4508
 
        dbgprintf(" restarted.\n");
4509
 
}
4510
 
 
4511
 
 
4512
 
/* Helper to cfline() and its helpers. Parses a template name
4513
 
 * from an "action" line. Must be called with the Line pointer
4514
 
 * pointing to the first character after the semicolon.
4515
 
 * rgerhards 2004-11-19
4516
 
 * changed function to work with OMSR. -- rgerhards, 2007-07-27
4517
 
 * the default template is to be used when no template is specified.
4518
 
 */
4519
 
rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName)
4520
 
{
4521
 
        uchar *p;
4522
 
        uchar *tplName;
4523
 
        DEFiRet;
4524
 
        rsCStrObj *pStrB;
4525
 
 
4526
 
        assert(pp != NULL);
4527
 
        assert(*pp != NULL);
4528
 
        assert(pOMSR != NULL);
4529
 
 
4530
 
        p =*pp;
4531
 
        /* a template must follow - search it and complain, if not found
4532
 
         */
4533
 
        skipWhiteSpace(&p);
4534
 
        if(*p == ';')
4535
 
                ++p; /* eat it */
4536
 
        else if(*p != '\0' && *p != '#') {
4537
 
                logerror("invalid character in selector line - ';template' expected");
4538
 
                iRet = RS_RET_ERR;
4539
 
                goto finalize_it;
4540
 
        }
4541
 
 
4542
 
        skipWhiteSpace(&p); /* go to begin of template name */
4543
 
 
4544
 
        if(*p == '\0') {
4545
 
                /* no template specified, use the default */
4546
 
                /* TODO: check NULL ptr */
4547
 
                tplName = (uchar*) strdup((char*)dfltTplName);
4548
 
        } else {
4549
 
                /* template specified, pick it up */
4550
 
                if((pStrB = rsCStrConstruct()) == NULL) {
4551
 
                        glblHadMemShortage = 1;
4552
 
                        iRet = RS_RET_OUT_OF_MEMORY;
4553
 
                        goto finalize_it;
4554
 
                }
4555
 
 
4556
 
                /* now copy the string */
4557
 
                while(*p && *p != '#' && !isspace((int) *p)) {
4558
 
                        CHKiRet(rsCStrAppendChar(pStrB, *p));
4559
 
                        ++p;
4560
 
                }
4561
 
                CHKiRet(rsCStrFinish(pStrB));
4562
 
                CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, &tplName, 0));
4563
 
        }
4564
 
 
4565
 
        iRet = OMSRsetEntry(pOMSR, iEntry, tplName, iTplOpts);
4566
 
        if(iRet != RS_RET_OK) goto finalize_it;
4567
 
 
4568
 
finalize_it:
4569
 
        *pp = p;
4570
 
 
4571
 
        return iRet;
4572
 
}
4573
 
 
4574
 
/* Helper to cfline(). Parses a file name up until the first
4575
 
 * comma and then looks for the template specifier. Tries
4576
 
 * to find that template.
4577
 
 * rgerhards 2004-11-18
4578
 
 * parameter pFileName must point to a buffer large enough
4579
 
 * to hold the largest possible filename.
4580
 
 * rgerhards, 2007-07-25
4581
 
 * updated to include OMSR pointer -- rgerhards, 2007-07-27
4582
 
 */
4583
 
rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts)
4584
 
{
4585
 
        register uchar *pName;
4586
 
        int i;
4587
 
        DEFiRet;
4588
 
 
4589
 
        assert(pOMSR != NULL);
4590
 
 
4591
 
        pName = pFileName;
4592
 
        i = 1; /* we start at 1 so that we reseve space for the '\0'! */
4593
 
        while(*p && *p != ';' && i < MAXFNAME) {
4594
 
                *pName++ = *p++;
4595
 
                ++i;
4596
 
        }
4597
 
        *pName = '\0';
4598
 
 
4599
 
        iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, (uchar*) " TradFmt");
4600
 
 
4601
 
        return iRet;
4602
 
}
4603
 
 
4604
 
 
4605
 
/*
4606
 
 * Helper to cfline(). This function takes the filter part of a traditional, PRI
4607
 
 * based line and decodes the PRIs given in the selector line. It processed the
4608
 
 * line up to the beginning of the action part. A pointer to that beginnig is
4609
 
 * passed back to the caller.
4610
 
 * rgerhards 2005-09-15
4611
 
 */
4612
 
static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register selector_t *f)
4613
 
{
4614
 
        uchar *p;
4615
 
        register uchar *q;
4616
 
        register int i, i2;
4617
 
        uchar *bp;
4618
 
        int pri;
4619
 
        int singlpri = 0;
4620
 
        int ignorepri = 0;
4621
 
        uchar buf[MAXLINE];
4622
 
        uchar xbuf[200];
4623
 
 
4624
 
        assert(pline != NULL);
4625
 
        assert(*pline != NULL);
4626
 
        assert(f != NULL);
4627
 
 
4628
 
        dbgprintf(" - traditional PRI filter\n");
4629
 
        errno = 0;      /* keep strerror_r() stuff out of logerror messages */
4630
 
 
4631
 
        f->f_filter_type = FILTER_PRI;
4632
 
        /* Note: file structure is pre-initialized to zero because it was
4633
 
         * created with calloc()!
4634
 
         */
4635
 
        for (i = 0; i <= LOG_NFACILITIES; i++) {
4636
 
                f->f_filterData.f_pmask[i] = TABLE_NOPRI;
4637
 
        }
4638
 
 
4639
 
        /* scan through the list of selectors */
4640
 
        for (p = *pline; *p && *p != '\t' && *p != ' ';) {
4641
 
 
4642
 
                /* find the end of this facility name list */
4643
 
                for (q = p; *q && *q != '\t' && *q++ != '.'; )
4644
 
                        continue;
4645
 
 
4646
 
                /* collect priority name */
4647
 
                for (bp = buf; *q && !strchr("\t ,;", *q); )
4648
 
                        *bp++ = *q++;
4649
 
                *bp = '\0';
4650
 
 
4651
 
                /* skip cruft */
4652
 
                while (strchr(",;", *q))
4653
 
                        q++;
4654
 
 
4655
 
                /* decode priority name */
4656
 
                if ( *buf == '!' ) {
4657
 
                        ignorepri = 1;
4658
 
                        for (bp=buf; *(bp+1); bp++)
4659
 
                                *bp=*(bp+1);
4660
 
                        *bp='\0';
4661
 
                }
4662
 
                else {
4663
 
                        ignorepri = 0;
4664
 
                }
4665
 
                if ( *buf == '=' )
4666
 
                {
4667
 
                        singlpri = 1;
4668
 
                        pri = decode(&buf[1], PriNames);
4669
 
                }
4670
 
                else {
4671
 
                        singlpri = 0;
4672
 
                        pri = decode(buf, PriNames);
4673
 
                }
4674
 
 
4675
 
                if (pri < 0) {
4676
 
                        snprintf((char*) xbuf, sizeof(xbuf), "unknown priority name \"%s\"", buf);
4677
 
                        logerror((char*) xbuf);
4678
 
                        return RS_RET_ERR;
4679
 
                }
4680
 
 
4681
 
                /* scan facilities */
4682
 
                while (*p && !strchr("\t .;", *p)) {
4683
 
                        for (bp = buf; *p && !strchr("\t ,;.", *p); )
4684
 
                                *bp++ = *p++;
4685
 
                        *bp = '\0';
4686
 
                        if (*buf == '*') {
4687
 
                                for (i = 0; i <= LOG_NFACILITIES; i++) {
4688
 
                                        if ( pri == INTERNAL_NOPRI ) {
4689
 
                                                if ( ignorepri )
4690
 
                                                        f->f_filterData.f_pmask[i] = TABLE_ALLPRI;
4691
 
                                                else
4692
 
                                                        f->f_filterData.f_pmask[i] = TABLE_NOPRI;
4693
 
                                        }
4694
 
                                        else if ( singlpri ) {
4695
 
                                                if ( ignorepri )
4696
 
                                                        f->f_filterData.f_pmask[i] &= ~(1<<pri);
4697
 
                                                else
4698
 
                                                        f->f_filterData.f_pmask[i] |= (1<<pri);
4699
 
                                        }
4700
 
                                        else
4701
 
                                        {
4702
 
                                                if ( pri == TABLE_ALLPRI ) {
4703
 
                                                        if ( ignorepri )
4704
 
                                                                f->f_filterData.f_pmask[i] = TABLE_NOPRI;
4705
 
                                                        else
4706
 
                                                                f->f_filterData.f_pmask[i] = TABLE_ALLPRI;
4707
 
                                                }
4708
 
                                                else
4709
 
                                                {
4710
 
                                                        if ( ignorepri )
4711
 
                                                                for (i2= 0; i2 <= pri; ++i2)
4712
 
                                                                        f->f_filterData.f_pmask[i] &= ~(1<<i2);
4713
 
                                                        else
4714
 
                                                                for (i2= 0; i2 <= pri; ++i2)
4715
 
                                                                        f->f_filterData.f_pmask[i] |= (1<<i2);
4716
 
                                                }
4717
 
                                        }
4718
 
                                }
4719
 
                        } else {
4720
 
                                i = decode(buf, FacNames);
4721
 
                                if (i < 0) {
4722
 
 
4723
 
                                        snprintf((char*) xbuf, sizeof(xbuf), "unknown facility name \"%s\"", buf);
4724
 
                                        logerror((char*) xbuf);
4725
 
                                        return RS_RET_ERR;
4726
 
                                }
4727
 
 
4728
 
                                if ( pri == INTERNAL_NOPRI ) {
4729
 
                                        if ( ignorepri )
4730
 
                                                f->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
4731
 
                                        else
4732
 
                                                f->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
4733
 
                                } else if ( singlpri ) {
4734
 
                                        if ( ignorepri )
4735
 
                                                f->f_filterData.f_pmask[i >> 3] &= ~(1<<pri);
4736
 
                                        else
4737
 
                                                f->f_filterData.f_pmask[i >> 3] |= (1<<pri);
4738
 
                                } else {
4739
 
                                        if ( pri == TABLE_ALLPRI ) {
4740
 
                                                if ( ignorepri )
4741
 
                                                        f->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
4742
 
                                                else
4743
 
                                                        f->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
4744
 
                                        } else {
4745
 
                                                if ( ignorepri )
4746
 
                                                        for (i2= 0; i2 <= pri; ++i2)
4747
 
                                                                f->f_filterData.f_pmask[i >> 3] &= ~(1<<i2);
4748
 
                                                else
4749
 
                                                        for (i2= 0; i2 <= pri; ++i2)
4750
 
                                                                f->f_filterData.f_pmask[i >> 3] |= (1<<i2);
4751
 
                                        }
4752
 
                                }
4753
 
                        }
4754
 
                        while (*p == ',' || *p == ' ')
4755
 
                                p++;
4756
 
                }
4757
 
 
4758
 
                p = q;
4759
 
        }
4760
 
 
4761
 
        /* skip to action part */
4762
 
        while (*p == '\t' || *p == ' ')
4763
 
                p++;
4764
 
 
4765
 
        *pline = p;
4766
 
        return RS_RET_OK;
4767
 
}
4768
 
 
4769
 
 
4770
 
/*
4771
 
 * Helper to cfline(). This function takes the filter part of a property
4772
 
 * based filter and decodes it. It processes the line up to the beginning
4773
 
 * of the action part. A pointer to that beginnig is passed back to the caller.
4774
 
 * rgerhards 2005-09-15
4775
 
 */
4776
 
static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f)
4777
 
{
4778
 
        rsParsObj *pPars;
4779
 
        rsCStrObj *pCSCompOp;
4780
 
        rsRetVal iRet;
4781
 
        int iOffset; /* for compare operations */
4782
 
 
4783
 
        assert(pline != NULL);
4784
 
        assert(*pline != NULL);
4785
 
        assert(f != NULL);
4786
 
 
4787
 
        dbgprintf(" - property-based filter\n");
4788
 
        errno = 0;      /* keep strerror_r() stuff out of logerror messages */
4789
 
 
4790
 
        f->f_filter_type = FILTER_PROP;
4791
 
 
4792
 
        /* create parser object starting with line string without leading colon */
4793
 
        if((iRet = rsParsConstructFromSz(&pPars, (*pline)+1)) != RS_RET_OK) {
4794
 
                logerrorInt("Error %d constructing parser object - ignoring selector", iRet);
4795
 
                return(iRet);
4796
 
        }
4797
 
 
4798
 
        /* read property */
4799
 
        iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1);
4800
 
        if(iRet != RS_RET_OK) {
4801
 
                logerrorInt("error %d parsing filter property - ignoring selector", iRet);
4802
 
                rsParsDestruct(pPars);
4803
 
                return(iRet);
4804
 
        }
4805
 
 
4806
 
        /* read operation */
4807
 
        iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1);
4808
 
        if(iRet != RS_RET_OK) {
4809
 
                logerrorInt("error %d compare operation property - ignoring selector", iRet);
4810
 
                rsParsDestruct(pPars);
4811
 
                return(iRet);
4812
 
        }
4813
 
 
4814
 
        /* we now first check if the condition is to be negated. To do so, we first
4815
 
         * must make sure we have at least one char in the param and then check the
4816
 
         * first one.
4817
 
         * rgerhards, 2005-09-26
4818
 
         */
4819
 
        if(rsCStrLen(pCSCompOp) > 0) {
4820
 
                if(*rsCStrGetBufBeg(pCSCompOp) == '!') {
4821
 
                        f->f_filterData.prop.isNegated = 1;
4822
 
                        iOffset = 1; /* ignore '!' */
4823
 
                } else {
4824
 
                        f->f_filterData.prop.isNegated = 0;
4825
 
                        iOffset = 0;
4826
 
                }
4827
 
        } else {
4828
 
                f->f_filterData.prop.isNegated = 0;
4829
 
                iOffset = 0;
4830
 
        }
4831
 
 
4832
 
        if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
4833
 
                f->f_filterData.prop.operation = FIOP_CONTAINS;
4834
 
        } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
4835
 
                f->f_filterData.prop.operation = FIOP_ISEQUAL;
4836
 
        } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "startswith", 10)) {
4837
 
                f->f_filterData.prop.operation = FIOP_STARTSWITH;
4838
 
        } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "regex", 5)) {
4839
 
                f->f_filterData.prop.operation = FIOP_REGEX;
4840
 
        } else {
4841
 
                logerrorSz("error: invalid compare operation '%s' - ignoring selector",
4842
 
                           (char*) rsCStrGetSzStrNoNULL(pCSCompOp));
4843
 
        }
4844
 
        rsCStrDestruct (pCSCompOp); /* no longer needed */
4845
 
 
4846
 
        /* read compare value */
4847
 
        iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
4848
 
        if(iRet != RS_RET_OK) {
4849
 
                logerrorInt("error %d compare value property - ignoring selector", iRet);
4850
 
                rsParsDestruct(pPars);
4851
 
                return(iRet);
4852
 
        }
4853
 
 
4854
 
        /* skip to action part */
4855
 
        if((iRet = parsSkipWhitespace(pPars)) != RS_RET_OK) {
4856
 
                logerrorInt("error %d skipping to action part - ignoring selector", iRet);
4857
 
                rsParsDestruct(pPars);
4858
 
                return(iRet);
4859
 
        }
4860
 
 
4861
 
        /* cleanup */
4862
 
        *pline = *pline + rsParsGetParsePointer(pPars) + 1;
4863
 
                /* we are adding one for the skipped initial ":" */
4864
 
 
4865
 
        return rsParsDestruct(pPars);
4866
 
}
4867
 
 
4868
 
 
4869
 
/*
4870
 
 * Helper to cfline(). This function interprets a BSD host selector line
4871
 
 * from the config file ("+/-hostname"). It stores it for further reference.
4872
 
 * rgerhards 2005-10-19
4873
 
 */
4874
 
static rsRetVal cflineProcessHostSelector(uchar **pline)
4875
 
{
4876
 
        rsRetVal iRet;
4877
 
 
4878
 
        assert(pline != NULL);
4879
 
        assert(*pline != NULL);
4880
 
        assert(**pline == '-' || **pline == '+');
4881
 
 
4882
 
        dbgprintf(" - host selector line\n");
4883
 
 
4884
 
        /* check include/exclude setting */
4885
 
        if(**pline == '+') {
4886
 
                eDfltHostnameCmpMode = HN_COMP_MATCH;
4887
 
        } else { /* we do not check for '-', it must be, else we wouldn't be here */
4888
 
                eDfltHostnameCmpMode = HN_COMP_NOMATCH;
4889
 
        }
4890
 
        (*pline)++;     /* eat + or - */
4891
 
 
4892
 
        /* the below is somewhat of a quick hack, but it is efficient (this is
4893
 
         * why it is in here. "+*" resets the tag selector with BSD syslog. We mimic
4894
 
         * this, too. As it is easy to check that condition, we do not fire up a
4895
 
         * parser process, just make sure we do not address beyond our space.
4896
 
         * Order of conditions in the if-statement is vital! rgerhards 2005-10-18
4897
 
         */
4898
 
        if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
4899
 
                dbgprintf("resetting BSD-like hostname filter\n");
4900
 
                eDfltHostnameCmpMode = HN_NO_COMP;
4901
 
                if(pDfltHostnameCmp != NULL) {
4902
 
                        if((iRet = rsCStrSetSzStr(pDfltHostnameCmp, NULL)) != RS_RET_OK)
4903
 
                                return(iRet);
4904
 
                }
4905
 
        } else {
4906
 
                dbgprintf("setting BSD-like hostname filter to '%s'\n", *pline);
4907
 
                if(pDfltHostnameCmp == NULL) {
4908
 
                        /* create string for parser */
4909
 
                        if((iRet = rsCStrConstructFromszStr(&pDfltHostnameCmp, *pline)) != RS_RET_OK)
4910
 
                                return(iRet);
4911
 
                } else { /* string objects exists, just update... */
4912
 
                        if((iRet = rsCStrSetSzStr(pDfltHostnameCmp, *pline)) != RS_RET_OK)
4913
 
                                return(iRet);
4914
 
                }
4915
 
        }
4916
 
        return RS_RET_OK;
4917
 
}
4918
 
 
4919
 
 
4920
 
/*
4921
 
 * Helper to cfline(). This function interprets a BSD tag selector line
4922
 
 * from the config file ("!tagname"). It stores it for further reference.
4923
 
 * rgerhards 2005-10-18
4924
 
 */
4925
 
static rsRetVal cflineProcessTagSelector(uchar **pline)
4926
 
{
4927
 
        rsRetVal iRet;
4928
 
 
4929
 
        assert(pline != NULL);
4930
 
        assert(*pline != NULL);
4931
 
        assert(**pline == '!');
4932
 
 
4933
 
        dbgprintf(" - programname selector line\n");
4934
 
 
4935
 
        (*pline)++;     /* eat '!' */
4936
 
 
4937
 
        /* the below is somewhat of a quick hack, but it is efficient (this is
4938
 
         * why it is in here. "!*" resets the tag selector with BSD syslog. We mimic
4939
 
         * this, too. As it is easy to check that condition, we do not fire up a
4940
 
         * parser process, just make sure we do not address beyond our space.
4941
 
         * Order of conditions in the if-statement is vital! rgerhards 2005-10-18
4942
 
         */
4943
 
        if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
4944
 
                dbgprintf("resetting programname filter\n");
4945
 
                if(pDfltProgNameCmp != NULL) {
4946
 
                        if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, NULL)) != RS_RET_OK)
4947
 
                                return(iRet);
4948
 
                }
4949
 
        } else {
4950
 
                dbgprintf("setting programname filter to '%s'\n", *pline);
4951
 
                if(pDfltProgNameCmp == NULL) {
4952
 
                        /* create string for parser */
4953
 
                        if((iRet = rsCStrConstructFromszStr(&pDfltProgNameCmp, *pline)) != RS_RET_OK)
4954
 
                                return(iRet);
4955
 
                } else { /* string objects exists, just update... */
4956
 
                        if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, *pline)) != RS_RET_OK)
4957
 
                                return(iRet);
4958
 
                }
4959
 
        }
4960
 
        return RS_RET_OK;
4961
 
}
4962
 
 
4963
 
 
4964
 
/* add an Action to the current selector
4965
 
 * The pOMSR is freed, as it is not needed after this function.
4966
 
 * Note: this function pulls global data that specifies action config state.
4967
 
 * rgerhards, 2007-07-27
4968
 
 */
4969
 
rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, int bSuspended)
4970
 
{
4971
 
        DEFiRet;
4972
 
        int i;
4973
 
        int iTplOpts;
4974
 
        uchar *pTplName;
4975
 
        action_t *pAction;
4976
 
        char errMsg[512];
4977
 
 
4978
 
        assert(ppAction != NULL);
4979
 
        assert(pMod != NULL);
4980
 
        assert(pOMSR != NULL);
4981
 
        dbgprintf("Module %s processed this config line.\n", modGetName(pMod));
4982
 
 
4983
 
        CHKiRet(actionConstruct(&pAction)); /* create action object first */
4984
 
        pAction->pMod = pMod;
4985
 
        pAction->pModData = pModData;
4986
 
        pAction->bExecWhenPrevSusp = bActExecWhenPrevSusp;
4987
 
 
4988
 
        /* check if we can obtain the template pointers - TODO: move to separat function? */
4989
 
        pAction->iNumTpls = OMSRgetEntryCount(pOMSR);
4990
 
        assert(pAction->iNumTpls >= 0); /* only debug check because this "can not happen" */
4991
 
        /* please note: iNumTpls may validly be zero. This is the case if the module
4992
 
         * does not request any templates. This sounds unlikely, but an actual example is
4993
 
         * the discard action, which does not require a string. -- rgerhards, 2007-07-30
4994
 
         */
4995
 
        if(pAction->iNumTpls > 0) {
4996
 
                /* we first need to create the template pointer array */
4997
 
                if((pAction->ppTpl = calloc(pAction->iNumTpls, sizeof(struct template *))) == NULL) {
4998
 
                        glblHadMemShortage = 1;
4999
 
                        ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
5000
 
                }
5001
 
                /* and now the array for doAction() message pointers */
5002
 
                if((pAction->ppMsgs = calloc(pAction->iNumTpls, sizeof(uchar *))) == NULL) {
5003
 
                        glblHadMemShortage = 1;
5004
 
                        ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
5005
 
                }
5006
 
        }
5007
 
        
5008
 
        for(i = 0 ; i < pAction->iNumTpls ; ++i) {
5009
 
                CHKiRet(OMSRgetEntry(pOMSR, i, &pTplName, &iTplOpts));
5010
 
                /* Ok, we got everything, so it now is time to look up the
5011
 
                 * template (Hint: templates MUST be defined before they are
5012
 
                 * used!)
5013
 
                 */
5014
 
                if((pAction->ppTpl[i] = tplFind((char*)pTplName, strlen((char*)pTplName))) == NULL) {
5015
 
                        snprintf(errMsg, sizeof(errMsg) / sizeof(char),
5016
 
                                 " Could not find template '%s' - action disabled\n",
5017
 
                                 pTplName);
5018
 
                        errno = 0;
5019
 
                        logerror(errMsg);
5020
 
                        ABORT_FINALIZE(RS_RET_NOT_FOUND);
5021
 
                }
5022
 
                /* check required template options */
5023
 
                if(   (iTplOpts & OMSR_RQD_TPL_OPT_SQL)
5024
 
                   && (pAction->ppTpl[i]->optFormatForSQL == 0)) {
5025
 
                        errno = 0;
5026
 
                        logerror("Action disabled. To use this action, you have to specify "
5027
 
                                "the SQL or stdSQL option in your template!\n");
5028
 
                        ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING);
5029
 
                }
5030
 
 
5031
 
                dbgprintf("template: '%s' assigned\n", pTplName);
5032
 
        }
5033
 
 
5034
 
        pAction->pMod = pMod;
5035
 
        pAction->pModData = pModData;
5036
 
        /* now check if the module is compatible with select features */
5037
 
        if(pMod->isCompatibleWithFeature(sFEATURERepeatedMsgReduction) == RS_RET_OK)
5038
 
                pAction->f_ReduceRepeated = bReduceRepeatMsgs;
5039
 
        else {
5040
 
                dbgprintf("module is incompatible with RepeatedMsgReduction - turned off\n");
5041
 
                pAction->f_ReduceRepeated = 0;
5042
 
        }
5043
 
        pAction->bEnabled = 1; /* action is enabled */
5044
 
 
5045
 
        if(bSuspended)
5046
 
                actionSuspend(pAction);
5047
 
 
5048
 
        *ppAction = pAction; /* finally store the action pointer */
5049
 
 
5050
 
finalize_it:
5051
 
        if(iRet == RS_RET_OK)
5052
 
                iRet = OMSRdestruct(pOMSR);
5053
 
        else {
5054
 
                /* do not overwrite error state! */
5055
 
                OMSRdestruct(pOMSR);
5056
 
                if(pAction != NULL)
5057
 
                        actionDestruct(pAction);
5058
 
        }
5059
 
 
5060
 
        return iRet;
5061
 
}
5062
 
 
5063
 
 
5064
 
/* read the filter part of a configuration line and store the filter
5065
 
 * in the supplied selector_t
5066
 
 * rgerhards, 2007-08-01
5067
 
 */
5068
 
static rsRetVal cflineDoFilter(uchar **pp, selector_t *f)
5069
 
{
5070
 
        DEFiRet;
5071
 
 
5072
 
        assert(pp != NULL);
5073
 
        assert(f != NULL);
5074
 
 
5075
 
        /* check which filter we need to pull... */
5076
 
        switch(**pp) {
5077
 
                case ':':
5078
 
                        iRet = cflineProcessPropFilter(pp, f);
5079
 
                        break;
5080
 
                default:
5081
 
                        iRet = cflineProcessTradPRIFilter(pp, f);
5082
 
                        break;
5083
 
        }
5084
 
 
5085
 
        /* we now check if there are some global (BSD-style) filter conditions
5086
 
         * and, if so, we copy them over. rgerhards, 2005-10-18
5087
 
         */
5088
 
        if(pDfltProgNameCmp != NULL)
5089
 
                if((iRet = rsCStrConstructFromCStr(&(f->pCSProgNameComp), pDfltProgNameCmp)) != RS_RET_OK)
5090
 
                        return(iRet);
5091
 
 
5092
 
        if(eDfltHostnameCmpMode != HN_NO_COMP) {
5093
 
                f->eHostnameCmpMode = eDfltHostnameCmpMode;
5094
 
                if((iRet = rsCStrConstructFromCStr(&(f->pCSHostnameComp), pDfltHostnameCmp)) != RS_RET_OK)
5095
 
                        return(iRet);
5096
 
        }
5097
 
 
5098
 
        return iRet;
5099
 
}
5100
 
 
5101
 
 
5102
 
/* process the action part of a selector line
5103
 
 * rgerhards, 2007-08-01
5104
 
 */
5105
 
static rsRetVal cflineDoAction(uchar **p, action_t **ppAction)
5106
 
{
5107
 
        DEFiRet;
5108
 
        modInfo_t *pMod;
5109
 
        omodStringRequest_t *pOMSR;
5110
 
        action_t *pAction;
5111
 
        void *pModData;
5112
 
 
5113
 
        assert(p != NULL);
5114
 
        assert(ppAction != NULL);
5115
 
 
5116
 
        /* loop through all modules and see if one picks up the line */
5117
 
        pMod = omodGetNxt(NULL);
5118
 
        while(pMod != NULL) {
5119
 
                iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR);
5120
 
                dbgprintf("tried selector action for %s: %d\n", modGetName(pMod), iRet);
5121
 
                if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {
5122
 
                        if((iRet = addAction(&pAction, pMod, pModData, pOMSR, (iRet == RS_RET_SUSPENDED)? 1 : 0)) == RS_RET_OK) {
5123
 
                                /* now check if the module is compatible with select features */
5124
 
                                if(pMod->isCompatibleWithFeature(sFEATURERepeatedMsgReduction) == RS_RET_OK)
5125
 
                                        pAction->f_ReduceRepeated = bReduceRepeatMsgs;
5126
 
                                else {
5127
 
                                        dbgprintf("module is incompatible with RepeatedMsgReduction - turned off\n");
5128
 
                                        pAction->f_ReduceRepeated = 0;
5129
 
                                }
5130
 
                                pAction->bEnabled = 1; /* action is enabled */
5131
 
                        }
5132
 
                        break;
5133
 
                }
5134
 
                else if(iRet != RS_RET_CONFLINE_UNPROCESSED) {
5135
 
                        /* In this case, the module would have handled the config
5136
 
                         * line, but some error occured while doing so. This error should
5137
 
                         * already by reported by the module. We do not try any other
5138
 
                         * modules on this line, because we found the right one.
5139
 
                         * rgerhards, 2007-07-24
5140
 
                         */
5141
 
                        dbgprintf("error %d parsing config line\n", (int) iRet);
5142
 
                        break;
5143
 
                }
5144
 
                pMod = omodGetNxt(pMod);
5145
 
        }
5146
 
 
5147
 
        *ppAction = pAction;
5148
 
        return iRet;
5149
 
}
5150
 
 
5151
 
 
5152
 
/* helper to selectorAddListCheckActions()
5153
 
 * This is the fucntion to be executed by llExecFunc
5154
 
 */
5155
 
DEFFUNC_llExecFunc(selectorAddListCheckActionsChecker)
5156
 
{
5157
 
        DEFiRet;
5158
 
        action_t *pAction = (action_t *) pData;
5159
 
 
5160
 
        assert(pAction != NULL);
5161
 
 
5162
 
        if(pAction->pMod->needUDPSocket(pAction->pModData) == RS_RET_TRUE) {
5163
 
                Forwarding++;
5164
 
        }
5165
 
 
5166
 
        return iRet;
5167
 
}
5168
 
 
5169
 
/* loop through a list of actions and perform necessary checks and
5170
 
 * housekeeping. This function must only be called when the owning
5171
 
 * selector_t looks valid and is not likely to be discarded. However,
5172
 
 * if we do not return RS_RET_OK, the caller MUST discard the
5173
 
 * owning selector_t. -- rgerhards, 2007-08-02
5174
 
*/
5175
 
static rsRetVal selectorAddListCheckActions(selector_t *f)
5176
 
{
5177
 
        DEFiRet;
5178
 
 
5179
 
        assert(f != NULL);
5180
 
 
5181
 
        CHKiRet(llExecFunc(&f->llActList, selectorAddListCheckActionsChecker, NULL));
5182
 
 
5183
 
finalize_it:
5184
 
        return iRet;
 
2363
        dbgprintf(" (re)started.\n");
 
2364
        ENDfunc
5185
2365
}
5186
2366
 
5187
2367
 
5194
2374
 * selector is NULL, which means we do not need to care about it at
5195
2375
 * all.  -- rgerhards, 2007-08-01
5196
2376
 */
5197
 
static rsRetVal selectorAddList(selector_t *f)
 
2377
rsRetVal
 
2378
selectorAddList(selector_t *f)
5198
2379
{
5199
2380
        DEFiRet;
5200
2381
        int iActionCnt;
5204
2385
        if(f != NULL) {
5205
2386
                CHKiRet(llGetNumElts(&f->llActList, &iActionCnt));
5206
2387
                if(iActionCnt == 0) {
5207
 
                        logerror("warning: selector line without actions will be discarded");
 
2388
                        errmsg.LogError(NO_ERRCODE, "warning: selector line without actions will be discarded");
5208
2389
                        selectorDestruct(f);
5209
2390
                } else {
5210
 
                        if((iRet = selectorAddListCheckActions(f)) != RS_RET_OK) {
5211
 
                                logerror("selector line will be discarded due to error in action(s)");
5212
 
                                selectorDestruct(f);
5213
 
                                goto finalize_it;
5214
 
                        }
5215
2391
                        /* successfully created an entry */
5216
2392
                        dbgprintf("selector line successfully processed\n");
5217
2393
                        /* TODO: we should use the linked list class for the selector list, else we need to add globals
5232
2408
        }
5233
2409
 
5234
2410
finalize_it:
5235
 
        return iRet;
 
2411
        RETiRet;
5236
2412
}
5237
2413
 
5238
2414
 
5239
 
/* Process a configuration file line in traditional "filter selector" format
 
2415
/* set the main message queue mode
 
2416
 * rgerhards, 2008-01-03
5240
2417
 */
5241
 
static rsRetVal cflineClassic(uchar *p, selector_t **pfCurr)
 
2418
static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *pszType)
5242
2419
{
5243
2420
        DEFiRet;
5244
 
        action_t *pAction;
5245
 
        selector_t *fCurr;
5246
 
 
5247
 
        assert(pfCurr != NULL);
5248
 
 
5249
 
        fCurr = *pfCurr;
5250
 
 
5251
 
        /* lines starting with '&' have no new filters and just add
5252
 
         * new actions to the currently processed selector.
5253
 
         */
5254
 
        if(*p == '&') {
5255
 
                ++p; /* eat '&' */
5256
 
                skipWhiteSpace(&p); /* on to command */
 
2421
 
 
2422
        if (!strcasecmp((char *) pszType, "fixedarray")) {
 
2423
                MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
 
2424
                dbgprintf("main message queue type set to FIXED_ARRAY\n");
 
2425
        } else if (!strcasecmp((char *) pszType, "linkedlist")) {
 
2426
                MainMsgQueType = QUEUETYPE_LINKEDLIST;
 
2427
                dbgprintf("main message queue type set to LINKEDLIST\n");
 
2428
        } else if (!strcasecmp((char *) pszType, "disk")) {
 
2429
                MainMsgQueType = QUEUETYPE_DISK;
 
2430
                dbgprintf("main message queue type set to DISK\n");
 
2431
        } else if (!strcasecmp((char *) pszType, "direct")) {
 
2432
                MainMsgQueType = QUEUETYPE_DIRECT;
 
2433
                dbgprintf("main message queue type set to DIRECT (no queueing at all)\n");
5257
2434
        } else {
5258
 
                /* we are finished with the current selector. So we now need to check
5259
 
                 * if it has any actions associated and, if so, link it to the linked
5260
 
                 * list. If it has nothing associated with it, we can simply discard
5261
 
                 * it. In any case, we create a fresh selector for our new filter.
5262
 
                 * We have one special case during initialization: then, the current
5263
 
                 * selector is NULL, which means we do not need to care about it at
5264
 
                 * all.  -- rgerhards, 2007-08-01
5265
 
                 */
5266
 
                CHKiRet(selectorAddList(fCurr));
5267
 
                CHKiRet(selectorConstruct(&fCurr)); /* create "fresh" selector */
5268
 
                CHKiRet(cflineDoFilter(&p, fCurr)); /* pull filters */
5269
 
        }
5270
 
 
5271
 
        CHKiRet(cflineDoAction(&p, &pAction));
5272
 
        CHKiRet(llAppend(&fCurr->llActList,  NULL, (void*) pAction));
5273
 
 
5274
 
finalize_it:
5275
 
        *pfCurr = fCurr;
5276
 
        return iRet;
5277
 
}
5278
 
 
5279
 
 
5280
 
/* process a configuration line
5281
 
 * I re-did this functon because it was desperately time to do so
5282
 
 * rgerhards, 2007-08-01
5283
 
 */
5284
 
static rsRetVal cfline(uchar *line, selector_t **pfCurr)
5285
 
{
5286
 
        DEFiRet;
5287
 
 
5288
 
        assert(line != NULL);
5289
 
 
5290
 
        dbgprintf("cfline: '%s'\n", line);
5291
 
 
5292
 
        /* check type of line and call respective processing */
5293
 
        switch(*line) {
5294
 
                case '!':
5295
 
                        iRet = cflineProcessTagSelector(&line);
5296
 
                        break;
5297
 
                case '+':
5298
 
                case '-':
5299
 
                        iRet = cflineProcessHostSelector(&line);
5300
 
                        break;
5301
 
                case '$':
5302
 
                        ++line; /* eat '$' */
5303
 
                        iRet = cfsysline(line);
5304
 
                        break;
5305
 
                default:
5306
 
                        iRet = cflineClassic(line, pfCurr);
5307
 
                        break;
5308
 
        }
5309
 
 
5310
 
        return iRet;
5311
 
}
5312
 
 
5313
 
 
5314
 
/*  Decode a symbolic name to a numeric value
5315
 
 */
5316
 
int decode(uchar *name, struct code *codetab)
5317
 
{
5318
 
        register struct code *c;
5319
 
        register uchar *p;
5320
 
        uchar buf[80];
5321
 
 
5322
 
        assert(name != NULL);
5323
 
        assert(codetab != NULL);
5324
 
 
5325
 
        dbgprintf("symbolic name: %s", name);
5326
 
        if (isdigit((int) *name))
5327
 
        {
5328
 
                dbgprintf("\n");
5329
 
                return (atoi((char*) name));
5330
 
        }
5331
 
        strncpy((char*) buf, (char*) name, 79);
5332
 
        for (p = buf; *p; p++)
5333
 
                if (isupper((int) *p))
5334
 
                        *p = tolower((int) *p);
5335
 
        for (c = codetab; c->c_name; c++)
5336
 
                if (!strcmp((char*) buf, (char*) c->c_name))
5337
 
                {
5338
 
                        dbgprintf(" ==> %d\n", c->c_val);
5339
 
                        return (c->c_val);
5340
 
                }
5341
 
        return (-1);
5342
 
}
5343
 
 
5344
 
extern void dbgprintf(char *fmt, ...) __attribute__((format(printf,1, 2)));
5345
 
void dbgprintf(char *fmt, ...)
5346
 
{
5347
 
#       ifdef USE_PTHREADS
5348
 
        static int bWasNL = FALSE;
5349
 
#       endif
5350
 
        va_list ap;
5351
 
 
5352
 
        if ( !(Debug && debugging_on) )
5353
 
                return;
5354
 
        
5355
 
#       ifdef USE_PTHREADS
5356
 
        /* The bWasNL handler does not really work. It works if no thread
5357
 
         * switching occurs during non-NL messages. Else, things are messed
5358
 
         * up. Anyhow, it works well enough to provide useful help during
5359
 
         * getting this up and running. It is questionable if the extra effort
5360
 
         * is worth fixing it, giving the limited appliability.
5361
 
         * rgerhards, 2005-10-25
5362
 
         * I have decided that it is not worth fixing it - especially as it works
5363
 
         * pretty well.
5364
 
         * rgerhards, 2007-06-15
5365
 
         */
5366
 
        if(bWasNL) {
5367
 
                fprintf(stdout, "%8.8d: ", (unsigned int) pthread_self());
5368
 
        }
5369
 
        bWasNL = (*(fmt + strlen(fmt) - 1) == '\n') ? TRUE : FALSE;
5370
 
#       endif
5371
 
        va_start(ap, fmt);
5372
 
        vfprintf(stdout, fmt, ap);
5373
 
        va_end(ap);
5374
 
 
5375
 
        fflush(stdout);
5376
 
        return;
 
2435
                errmsg.LogError(NO_ERRCODE, "unknown mainmessagequeuetype parameter: %s", (char *) pszType);
 
2436
                iRet = RS_RET_INVALID_PARAMS;
 
2437
        }
 
2438
        free(pszType); /* no longer needed */
 
2439
 
 
2440
        RETiRet;
5377
2441
}
5378
2442
 
5379
2443
 
5413
2477
 * \param DstSize       Maximum numbers of characters to store.
5414
2478
 * \param cSep          Separator char.
5415
2479
 * \ret int             Returns 0 if no error occured.
 
2480
 *
 
2481
 * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time
 
2482
 * so that it treats ' ' as a request for whitespace. But in general, the function and its callers
 
2483
 * should be changed over time, this is not really very good code...
5416
2484
 */
5417
2485
int getSubString(uchar **ppSrc,  char *pDst, size_t DstSize, char cSep)
5418
2486
{
5419
2487
        uchar *pSrc = *ppSrc;
5420
2488
        int iErr = 0; /* 0 = no error, >0 = error */
5421
 
        while(*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
 
2489
        while((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
5422
2490
                *pDst++ = *(pSrc)++;
5423
2491
                DstSize--;
5424
2492
        }
5425
2493
        /* check if the Dst buffer was to small */
5426
 
        if (*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0')
5427
 
        { 
 
2494
        if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') { 
5428
2495
                dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
5429
2496
                iErr = 1;
5430
2497
        }       
5440
2507
}
5441
2508
 
5442
2509
 
5443
 
/* print out which socket we are listening on. This is only
5444
 
 * a debug aid. rgerhards, 2007-07-02
5445
 
 */
5446
 
static void debugListenInfo(int fd, char *type)
5447
 
{
5448
 
        char *szFamily;
5449
 
        int port;
5450
 
        struct sockaddr sa;
5451
 
        struct sockaddr_in *ipv4;
5452
 
        struct sockaddr_in6 *ipv6;
5453
 
        socklen_t saLen = sizeof(sa);
5454
 
 
5455
 
        if(getsockname(fd, &sa, &saLen) == 0) {
5456
 
                switch(sa.sa_family) {
5457
 
                case PF_INET:
5458
 
                        szFamily = "IPv4";
5459
 
                        ipv4 = (struct sockaddr_in*) &sa;
5460
 
                        port = ntohs(ipv4->sin_port);
5461
 
                        break;
5462
 
                case PF_INET6:
5463
 
                        szFamily = "IPv6";
5464
 
                        ipv6 = (struct sockaddr_in6*) &sa;
5465
 
                        port = ntohs(ipv6->sin6_port);
5466
 
                        break;
5467
 
                default:
5468
 
                        szFamily = "other";
5469
 
                        port = -1;
5470
 
                        break;
5471
 
                }
5472
 
                dbgprintf("Listening on %s syslogd socket %d (%s/port %d).\n",
5473
 
                        type, fd, szFamily, port);
5474
 
                return;
5475
 
        }
5476
 
 
5477
 
        /* we can not obtain peer info. We are just providing
5478
 
         * debug info, so this is no reason to break the program
5479
 
         * or do any serious error reporting.
5480
 
         */
5481
 
        dbgprintf("Listening on syslogd socket %d - could not obtain peer info.\n", fd);
5482
 
}
5483
 
 
5484
 
 
5485
2510
/* this function pulls all internal messages from the buffer
5486
2511
 * and puts them into the processing engine.
5487
2512
 * We can only do limited error handling, as this would not
5495
2520
        msg_t *pMsg;
5496
2521
 
5497
2522
        while(iminternalRemoveMsg(&iPri, &pMsg, &iFlags) == RS_RET_OK) {
5498
 
                logmsg(iPri, pMsg, iFlags);
5499
 
                MsgDestruct(pMsg);
5500
 
        }
5501
 
}
5502
 
 
5503
 
 
5504
 
/* helper function for mainloop(). This is used to add all module
5505
 
 * writeFDsfor Select via llExecFunc().
5506
 
 * rgerhards, 2007-08-02
5507
 
 */
5508
 
typedef struct selectHelperWriteFDSInfo_s { /* struct for pParam */
5509
 
        fd_set *pWritefds;
5510
 
        int *pMaxfds;
5511
 
} selectHelperWriteFDSInfo_t;
5512
 
DEFFUNC_llExecFunc(mainloopAddModWriteFDSforSelect)
5513
 
{
5514
 
        DEFiRet;
5515
 
        action_t *pAction = (action_t*) pData;
5516
 
        selectHelperWriteFDSInfo_t *pState = (selectHelperWriteFDSInfo_t*) pParam;
5517
 
        short fdMod;
5518
 
 
5519
 
        assert(pAction != NULL);
5520
 
        assert(pState != NULL);
5521
 
 
5522
 
        if(pAction->pMod->getWriteFDForSelect(pAction->pModData, &fdMod) == RS_RET_OK) {
5523
 
           FD_SET(fdMod, pState->pWritefds);
5524
 
                if(fdMod > *pState->pMaxfds)
5525
 
                        *pState->pMaxfds = fdMod;
5526
 
                }
5527
 
 
5528
 
        return iRet;
5529
 
}
5530
 
 
5531
 
 
5532
 
/* helper function for mainloop(). This is used to call module action
5533
 
 * handlers after select if a fd is writable.
5534
 
 * HINT: when we change to the new threading model, this function
5535
 
 * is probably no longer needed.
5536
 
 * rgerhards, 2007-08-02
5537
 
 */
5538
 
DEFFUNC_llExecFunc(mainloopCallWithWritableFDsActions)
5539
 
{
5540
 
        DEFiRet;
5541
 
        action_t *pAction = (action_t*) pData;
5542
 
        selectHelperWriteFDSInfo_t *pState = (selectHelperWriteFDSInfo_t*) pParam;
5543
 
        short fdMod;
5544
 
 
5545
 
        assert(pAction != NULL);
5546
 
        assert(pState != NULL);
5547
 
 
5548
 
        if(pAction->pMod->getWriteFDForSelect(pAction->pModData, &fdMod) == RS_RET_OK) {
5549
 
                if(FD_ISSET(fdMod, pState->pWritefds)) {
5550
 
                        if((iRet = pAction->pMod->onSelectReadyWrite(pAction->pModData))
5551
 
                           != RS_RET_OK) {
5552
 
                                dbgprintf("error %d from onSelectReadyWrite() - continuing\n", iRet);
5553
 
                        }
5554
 
                        if(--(pState->pMaxfds) == 0) {
5555
 
                                ABORT_FINALIZE(RS_RET_FINISHED); /* all processed, nothing left to do */
5556
 
                        }
5557
 
                }
5558
 
           }
5559
 
 
5560
 
finalize_it:
5561
 
        return iRet;
5562
 
}
5563
 
 
5564
 
 
5565
 
/* process the select() selector array after the successful select.
5566
 
 * processing is completed as soon as all selectors needing attention
5567
 
 * are processed.
5568
 
 * rgerhards, 2007-08-08
5569
 
 */
5570
 
static rsRetVal processSelectAfter(int maxfds, int nfds, fd_set *pReadfds, fd_set *pWritefds)
5571
 
{
5572
 
        DEFiRet;
5573
 
        rsRetVal iRetLL;
5574
 
        int i;
5575
 
        int fd;
5576
 
        char line[MAXLINE +1];
5577
 
        selectHelperWriteFDSInfo_t writeFDSInfo;
5578
 
#ifdef  SYSLOG_INET
5579
 
        selector_t *f;
5580
 
        struct sockaddr_storage frominet;
5581
 
        socklen_t socklen;
5582
 
        uchar fromHost[NI_MAXHOST];
5583
 
        uchar fromHostFQDN[NI_MAXHOST];
5584
 
        int iTCPSess;
5585
 
        ssize_t l;
5586
 
#endif  /* #ifdef SYSLOG_INET */
5587
 
 
5588
 
        /* the following macro is used to decrement the number of to-be-probed
5589
 
         * fds and abort this function when we are done with all.
5590
 
         */
5591
 
#       define FDPROCESSED() if(--nfds == 0) { ABORT_FINALIZE(RS_RET_OK); }
5592
 
 
5593
 
        if (nfds < 0) {
5594
 
                if (errno != EINTR)
5595
 
                        logerror("select");
5596
 
                dbgprintf("Select interrupted.\n");
5597
 
                ABORT_FINALIZE(RS_RET_OK); /* we are done in any case */
5598
 
        }
5599
 
 
5600
 
        if(debugging_on) {
5601
 
                dbgprintf("\nSuccessful select, descriptor count = %d, Activity on: ", nfds);
5602
 
                for (i = 0; i <= maxfds; ++i)
5603
 
                        if ( FD_ISSET(i, pReadfds) )
5604
 
                                dbgprintf("%d ", i);
5605
 
                dbgprintf(("\n"));
5606
 
        }
5607
 
 
5608
 
#ifdef SYSLOG_INET
5609
 
        /* Now check the TCP send sockets. So far, we only see if they become
5610
 
         * writable and then change their internal status. No real async
5611
 
         * writing is currently done. This code will be replaced once liblogging
5612
 
         * is used, thus we try not to focus too much on it.
5613
 
         *
5614
 
         * IMPORTANT: With the current code, the writefds must be checked first,
5615
 
         * because the readfds might have messages to be forwarded, which
5616
 
         * rely on the status setting that is done here!
5617
 
         * rgerhards 2005-07-20
5618
 
         *
5619
 
         * liblogging implementation will not happen as anticipated above. So
5620
 
         * this code here will stay for quite a while.
5621
 
         * rgerhards, 2006-12-07
5622
 
         */
5623
 
        writeFDSInfo.pWritefds = pWritefds;
5624
 
        writeFDSInfo.pMaxfds = &nfds;
5625
 
        for(f = Files; f != NULL ; f = f->f_next) {
5626
 
                iRetLL = llExecFunc(&f->llActList, mainloopCallWithWritableFDsActions, &writeFDSInfo);
5627
 
                if(iRetLL == RS_RET_FINISHED) {
5628
 
                        ABORT_FINALIZE(RS_RET_OK); /* we are done in this case */
5629
 
                }
5630
 
        }
5631
 
#endif /* #ifdef SYSLOG_INET */
5632
 
#ifdef SYSLOG_UNIXAF
5633
 
        for (i = 0; i < nfunix; i++) {
5634
 
                if ((fd = funix[i]) != -1 && FD_ISSET(fd, pReadfds)) {
5635
 
                        int iRcvd;
5636
 
                        iRcvd = recv(fd, line, MAXLINE - 1, 0);
5637
 
                        dbgprintf("Message from UNIX socket: #%d\n", fd);
5638
 
                        if (iRcvd > 0) {
5639
 
                                printchopped(LocalHostName, line, iRcvd,  fd, funixParseHost[i]);
5640
 
                        } else if (iRcvd < 0 && errno != EINTR) {
5641
 
                                char errStr[1024];
5642
 
                                dbgprintf("UNIX socket error: %d = %s.\n", \
5643
 
                                        errno, strerror_r(errno, errStr, sizeof(errStr)));
5644
 
                                logerror("recvfrom UNIX");
5645
 
                        }
5646
 
                FDPROCESSED();
5647
 
                }
5648
 
        }
5649
 
#endif
5650
 
 
5651
 
#ifdef SYSLOG_INET
5652
 
       if (finet != NULL && AcceptRemote) {
5653
 
               for (i = 0; i < *finet; i++) {
5654
 
                       if (FD_ISSET(finet[i+1], pReadfds)) {
5655
 
                               socklen = sizeof(frominet);
5656
 
                               memset(line, 0xff, sizeof(line)); // TODO: I think we need this for debug only - remove after bug hunt
5657
 
                               l = recvfrom(finet[i+1], line, MAXLINE - 1, 0,
5658
 
                                            (struct sockaddr *)&frominet, &socklen);
5659
 
                               if (l > 0) {
5660
 
                                       if(cvthname(&frominet, fromHost, fromHostFQDN) == RS_RET_OK) {
5661
 
                                               dbgprintf("Message from inetd socket: #%d, host: %s\n",
5662
 
                                                       finet[i+1], fromHost);
5663
 
                                               /* Here we check if a host is permitted to send us
5664
 
                                                * syslog messages. If it isn't, we do not further
5665
 
                                                * process the message but log a warning (if we are
5666
 
                                                * configured to do this).
5667
 
                                                * rgerhards, 2005-09-26
5668
 
                                                */
5669
 
                                               if(isAllowedSender(pAllowedSenders_UDP,
5670
 
                                                  (struct sockaddr *)&frominet, (char*)fromHostFQDN)) {
5671
 
                                                       printchopped((char*)fromHost, line, l,  finet[i+1], 1);
5672
 
                                               } else {
5673
 
                                                       if(option_DisallowWarning) {
5674
 
                                                               logerrorSz("UDP message from disallowed sender %s discarded",
5675
 
                                                                          (char*)fromHost);
5676
 
                                                       }        
5677
 
                                               }
5678
 
                                       }
5679
 
                               } else if (l < 0 && errno != EINTR && errno != EAGAIN) {
5680
 
                                        char errStr[1024];
5681
 
                                       dbgprintf("INET socket error: %d = %s.\n",
5682
 
                                                        errno, strerror_r(errno, errStr, sizeof(errStr)));
5683
 
                                               logerror("recvfrom inet");
5684
 
                                               /* should be harmless */
5685
 
                                               sleep(1);
5686
 
                                       }
5687
 
                        FDPROCESSED();
5688
 
                        }
5689
 
               }
5690
 
        }
5691
 
 
5692
 
        if(sockTCPLstn != NULL && *sockTCPLstn) {
5693
 
                for (i = 0; i < *sockTCPLstn; i++) {
5694
 
                        if (FD_ISSET(sockTCPLstn[i+1], pReadfds)) {
5695
 
                                dbgprintf("New connect on TCP inetd socket: #%d\n", sockTCPLstn[i+1]);
5696
 
                                TCPSessAccept(sockTCPLstn[i+1]);
5697
 
                                FDPROCESSED();
5698
 
                        }
5699
 
                }
5700
 
 
5701
 
                /* now check the sessions */
5702
 
                iTCPSess = TCPSessGetNxtSess(-1);
5703
 
                while(iTCPSess != -1) {
5704
 
                        int fdSess;
5705
 
                        int state;
5706
 
                        fdSess = pTCPSessions[iTCPSess].sock;
5707
 
                        if(FD_ISSET(fdSess, pReadfds)) {
5708
 
                                char buf[MAXLINE];
5709
 
                                dbgprintf("tcp session socket with new data: #%d\n", fdSess);
5710
 
 
5711
 
                                /* Receive message */
5712
 
                                state = recv(fdSess, buf, sizeof(buf), 0);
5713
 
                                if(state == 0) {
5714
 
                                        /* process any incomplete frames left over */
5715
 
                                        TCPSessPrepareClose(iTCPSess);
5716
 
                                        /* Session closed */
5717
 
                                        TCPSessClose(iTCPSess);
5718
 
                                } else if(state == -1) {
5719
 
                                        logerrorInt("TCP session %d will be closed, error ignored\n",
5720
 
                                                    fdSess);
5721
 
                                        TCPSessClose(iTCPSess);
5722
 
                                } else {
5723
 
                                        /* valid data received, process it! */
5724
 
                                        if(TCPSessDataRcvd(iTCPSess, buf, state) == 0) {
5725
 
                                                /* in this case, something went awfully wrong.
5726
 
                                                 * We are instructed to terminate the session.
5727
 
                                                 */
5728
 
                                                logerrorInt("Tearing down TCP Session %d - see "
5729
 
                                                            "previous messages for reason(s)\n",
5730
 
                                                            iTCPSess);
5731
 
                                                TCPSessClose(iTCPSess);
5732
 
                                        }
5733
 
                                }
5734
 
                                FDPROCESSED();
5735
 
                        }
5736
 
                        iTCPSess = TCPSessGetNxtSess(iTCPSess);
5737
 
                }
5738
 
        }
5739
 
 
5740
 
#endif
5741
 
finalize_it:
5742
 
        return iRet;
 
2523
                logmsg(pMsg, iFlags);
 
2524
        }
5743
2525
}
5744
2526
 
5745
2527
 
5746
2528
/* This is the main processing loop. It is called after successful initialization.
5747
2529
 * When it returns, the syslogd terminates.
 
2530
 * Its sole function is to provide some housekeeping things. The real work is done
 
2531
 * by the other threads spawned.
5748
2532
 */
5749
 
static void mainloop(void)
 
2533
static void
 
2534
mainloop(void)
5750
2535
{
5751
 
        fd_set readfds;
5752
 
        int i;
5753
 
        int maxfds;
5754
 
        int nfds;
5755
 
#ifdef  SYSLOG_INET
5756
 
        selectHelperWriteFDSInfo_t writeFDSInfo;
5757
 
        fd_set writefds;
5758
 
        selector_t *f;
5759
 
        int iTCPSess;
5760
 
#endif  /* #ifdef SYSLOG_INET */
5761
 
#ifdef  BSD
5762
 
#ifdef  USE_PTHREADS
5763
2536
        struct timeval tvSelectTimeout;
5764
 
#endif
5765
 
#endif
5766
2537
 
 
2538
        BEGINfunc
5767
2539
        while(!bFinished){
5768
 
                errno  = 0;
5769
 
                maxfds = 0;
5770
 
                FD_ZERO (&readfds);
5771
 
 
5772
2540
                /* first check if we have any internal messages queued and spit them out */
 
2541
                /* TODO: do we need this any longer? I doubt it, but let's care about it
 
2542
                 * later -- rgerhards, 2007-12-21
 
2543
                 */
5773
2544
                processImInternal();
5774
2545
 
5775
 
#ifdef SYSLOG_UNIXAF
5776
 
                /* Add the Unix Domain Sockets to the list of read
5777
 
                 * descriptors.
5778
 
                 * rgerhards 2005-08-01: we must now check if there are
5779
 
                 * any local sockets to listen to at all. If the -o option
5780
 
                 * is given without -a, we do not need to listen at all..
5781
 
                 */
5782
 
                /* Copy master connections */
5783
 
                for (i = startIndexUxLocalSockets; i < nfunix; i++) {
5784
 
                        if (funix[i] != -1) {
5785
 
                                FD_SET(funix[i], &readfds);
5786
 
                                if (funix[i]>maxfds) maxfds=funix[i];
5787
 
                        }
5788
 
                }
5789
 
#endif
5790
 
#ifdef SYSLOG_INET
5791
 
                /* Add the UDP listen sockets to the list of read descriptors.
5792
 
                 */
5793
 
                if(finet != NULL && AcceptRemote) {
5794
 
                        for (i = 0; i < *finet; i++) {
5795
 
                                if (finet[i+1] != -1) {
5796
 
                                        if(Debug)
5797
 
                                                debugListenInfo(finet[i+1], "UDP");
5798
 
                                        FD_SET(finet[i+1], &readfds);
5799
 
                                        if(finet[i+1]>maxfds) maxfds=finet[i+1];
5800
 
                                }
5801
 
                        }
5802
 
                }
5803
 
 
5804
 
                /* Add the TCP listen sockets to the list of read descriptors.
5805
 
                 */
5806
 
                if(sockTCPLstn != NULL && *sockTCPLstn) {
5807
 
                        for (i = 0; i < *sockTCPLstn; i++) {
5808
 
                                /* The if() below is theoretically not needed, but I leave it in
5809
 
                                 * so that a socket may become unsuable during execution. That
5810
 
                                 * feature is not yet supported by the current code base.
5811
 
                                 */
5812
 
                                if (sockTCPLstn[i+1] != -1) {
5813
 
                                        if(Debug)
5814
 
                                                debugListenInfo(sockTCPLstn[i+1], "TCP");
5815
 
                                        FD_SET(sockTCPLstn[i+1], &readfds);
5816
 
                                        if(sockTCPLstn[i+1]>maxfds) maxfds=sockTCPLstn[i+1];
5817
 
                                }
5818
 
                        }
5819
 
                        /* do the sessions */
5820
 
                        iTCPSess = TCPSessGetNxtSess(-1);
5821
 
                        while(iTCPSess != -1) {
5822
 
                                int fdSess;
5823
 
                                fdSess = pTCPSessions[iTCPSess].sock;
5824
 
                                dbgprintf("Adding TCP Session %d\n", fdSess);
5825
 
                                FD_SET(fdSess, &readfds);
5826
 
                                if (fdSess>maxfds) maxfds=fdSess;
5827
 
                                /* now get next... */
5828
 
                                iTCPSess = TCPSessGetNxtSess(iTCPSess);
5829
 
                        }
5830
 
                }
5831
 
 
5832
 
                /* TODO: activate the code below only if we actually need to check
5833
 
                 * for outstanding writefds.
5834
 
                 */
5835
 
                if(1) {
5836
 
                        /* Now add the TCP output sockets to the writefds set. This implementation
5837
 
                         * is not optimal (performance-wise) and it should be replaced with something
5838
 
                         * better in the longer term. I've not yet done this, as this code is
5839
 
                         * scheduled to be replaced after the liblogging integration.
5840
 
                         * rgerhards 2005-07-20
5841
 
                         */
5842
 
                        FD_ZERO(&writefds);
5843
 
                        writeFDSInfo.pWritefds = &writefds;
5844
 
                        writeFDSInfo.pMaxfds = &maxfds;
5845
 
                        for (f = Files; f != NULL ; f = f->f_next) {
5846
 
                                llExecFunc(&f->llActList, mainloopAddModWriteFDSforSelect, &writeFDSInfo);
5847
 
                        }
5848
 
                }
5849
 
#endif
5850
 
 
5851
 
                if ( debugging_on ) {
5852
 
                        dbgprintf("----------------------------------------\n");
5853
 
                        dbgprintf("Calling select, active file descriptors (max %d): ", maxfds);
5854
 
                        for (nfds= 0; nfds <= maxfds; ++nfds)
5855
 
                                if ( FD_ISSET(nfds, &readfds) )
5856
 
                                        dbgprintf("%d ", nfds);
5857
 
                        dbgprintf("\n");
5858
 
                }
5859
 
 
5860
 
#define  MAIN_SELECT_TIMEVAL NULL
5861
 
#ifdef BSD
5862
 
#ifdef USE_PTHREADS
5863
 
                /* There seems to be a problem with BSD and threads. When running on
5864
 
                 * multiple threads, a signal will not cause the select call to be
5865
 
                 * interrrupted. I am not sure if this is by design or an bug (some
5866
 
                 * information on the web let's me think it is a bug), but that really
5867
 
                 * does not matter. The issue with our code is that we will not gain
5868
 
                 * control when rsyslogd is terminated or huped. What I am doing now is
5869
 
                 * make the select call timeout after 10 seconds, so that we can check
5870
 
                 * the condition then. Obviously, this causes some sluggish behaviour and
5871
 
                 * also the loss of some (very few) cpu cycles. Both, I think, are
5872
 
                 * absolutely acceptable.
5873
 
                 * rgerhards, 2005-10-26
5874
 
                 * TODO: I got some information: this seems to be expected signal() behaviour
5875
 
                 * we should investigate the use of sigaction() (see klogd.c for an sample).
5876
 
                 * rgerhards, 2007-06-22
5877
 
                 * rgerhards, 2007-09-11: code has been converted to sigaction() now. We need
5878
 
                 * to re-check on BSD, I think the issue is now solved.
5879
 
                 */
5880
 
                tvSelectTimeout.tv_sec = 10;
 
2546
                /* this is now just a wait */
 
2547
                tvSelectTimeout.tv_sec = TIMERINTVL;
5881
2548
                tvSelectTimeout.tv_usec = 0;
5882
 
#               undef MAIN_SELECT_TIMEVAL 
5883
 
#               define MAIN_SELECT_TIMEVAL &tvSelectTimeout
5884
 
#endif
5885
 
#endif
5886
 
#ifdef SYSLOG_INET
5887
 
#define MAIN_SELECT_WRITEFDS (fd_set *) &writefds
5888
 
#else
5889
 
#define MAIN_SELECT_WRITEFDS NULL
5890
 
#endif
5891
 
                nfds = select(maxfds+1, (fd_set *) &readfds, MAIN_SELECT_WRITEFDS,
5892
 
                                  (fd_set *) NULL, MAIN_SELECT_TIMEVAL);
5893
 
 
5894
 
                if(bRequestDoMark) {
5895
 
                        domark();
5896
 
                        bRequestDoMark = 0;
5897
 
                        /* We do not use continue, because domark() is carried out
5898
 
                         * only when something else happened.
5899
 
                         */
5900
 
                }
 
2549
                select(1, NULL, NULL, NULL, &tvSelectTimeout);
 
2550
                if(bFinished)
 
2551
                        break;  /* exit as quickly as possible - see long comment below */
 
2552
 
 
2553
                /* If we received a HUP signal, we call doFlushRptdMsgs() a bit early. This
 
2554
                 * doesn't matter, because doFlushRptdMsgs() checks timestamps. What may happen,
 
2555
                 * however, is that the too-early call may lead to a bit too-late output
 
2556
                 * of "last message repeated n times" messages. But that is quite acceptable.
 
2557
                 * rgerhards, 2007-12-21
 
2558
                 * ... and just to explain, we flush here because that is exactly what the mainloop
 
2559
                 * shall do - provide a periodic interval in which not-yet-flushed messages will
 
2560
                 * be flushed. Be careful, there is a potential race condition: doFlushRptdMsgs()
 
2561
                 * needs to aquire a lock on the action objects. If, however, long-running consumers
 
2562
                 * cause the main queue worker threads to lock them for a long time, we may receive
 
2563
                 * a starvation condition, resulting in the mainloop being held on lock for an extended
 
2564
                 * period of time. That, in turn, could lead to unresponsiveness to termination
 
2565
                 * requests. It is especially important that the bFinished flag is checked before
 
2566
                 * doFlushRptdMsgs() is called (I know because I ran into that situation). I am
 
2567
                 * not yet sure if the remaining probability window of a termination-related
 
2568
                 * problem is large enough to justify changing the code - I would consider it
 
2569
                 * extremely unlikely that the problem ever occurs in practice. Fixing it would
 
2570
                 * require not only a lot of effort but would cost considerable performance. So
 
2571
                 * for the time being, I think the remaining risk can be accepted.
 
2572
                 * rgerhards, 2008-01-10
 
2573
                 */
 
2574
                doFlushRptdMsgs();
 
2575
 
5901
2576
                if(restart) {
5902
2577
                        dbgprintf("\nReceived SIGHUP, reloading rsyslogd.\n");
5903
 
                        /* worker thread is stopped as part of init() */
 
2578
                        /* main queue is stopped as part of init() */
5904
2579
                        init();
5905
2580
                        restart = 0;
5906
2581
                        continue;
5907
2582
                }
5908
 
                if (nfds == 0) {
5909
 
                        dbgprintf("No select activity.\n");
5910
 
                        continue;
5911
 
                }
5912
 
 
5913
 
                processSelectAfter(maxfds, nfds, &readfds, MAIN_SELECT_WRITEFDS);
5914
 
 
5915
 
#undef MAIN_SELECT_TIMEVAL 
5916
 
#undef MAIN_SELECT_WRITEFDS
5917
2583
        }
 
2584
        ENDfunc
5918
2585
}
5919
2586
 
5920
2587
/* If user is not root, prints warnings or even exits 
5924
2591
 */
5925
2592
static void checkPermissions()
5926
2593
{
 
2594
#if 0
 
2595
        /* TODO: this function must either be redone or removed - now with the input modules,
 
2596
         * there is no such simple check we can do. What we can check, however, is if there is
 
2597
         * any input module active and terminate, if not. -- rgerhards, 2007-12-26
 
2598
         */
5927
2599
        /* we are not root */
5928
2600
        if (geteuid() != 0)
5929
2601
        {
5948
2620
                }
5949
2621
#endif
5950
2622
        }
 
2623
#endif
5951
2624
}
5952
2625
 
5953
2626
 
5958
2631
{
5959
2632
        DEFiRet;
5960
2633
 
5961
 
        if((iRet = doModInit(modInitFile, (uchar*) "builtin-file", NULL)) != RS_RET_OK)
5962
 
                return iRet;
 
2634
        if((iRet = module.doModInit(modInitFile, (uchar*) "builtin-file", NULL)) != RS_RET_OK) {
 
2635
                RETiRet;
 
2636
        }
5963
2637
#ifdef SYSLOG_INET
5964
 
        if((iRet = doModInit(modInitFwd, (uchar*) "builtin-fwd", NULL)) != RS_RET_OK)
5965
 
                return iRet;
 
2638
        if((iRet = module.doModInit(modInitFwd, (uchar*) "builtin-fwd", NULL)) != RS_RET_OK) {
 
2639
                RETiRet;
 
2640
        }
5966
2641
#endif
5967
 
        if((iRet = doModInit(modInitShell, (uchar*) "builtin-shell", NULL)) != RS_RET_OK)
5968
 
                return iRet;
5969
 
        if((iRet = doModInit(modInitDiscard, (uchar*) "builtin-discard", NULL)) != RS_RET_OK)
5970
 
                return iRet;
 
2642
        if((iRet = module.doModInit(modInitShell, (uchar*) "builtin-shell", NULL)) != RS_RET_OK) {
 
2643
                RETiRet;
 
2644
        }
 
2645
        if((iRet = module.doModInit(modInitDiscard, (uchar*) "builtin-discard", NULL)) != RS_RET_OK) {
 
2646
                RETiRet;
 
2647
        }
5971
2648
 
5972
2649
        /* dirty, but this must be for the time being: the usrmsg module must always be
5973
2650
         * loaded as last module. This is because it processes any time of action selector.
5978
2655
         * User names now must begin with:
5979
2656
         *   [a-zA-Z0-9_.]
5980
2657
         */
5981
 
        if((iRet = doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg", NULL)) != RS_RET_OK)
5982
 
                return iRet;
 
2658
        if((iRet = module.doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg", NULL)) != RS_RET_OK)
 
2659
                RETiRet;
5983
2660
 
5984
2661
        /* ok, initialization of the command handler probably does not 100% belong right in
5985
2662
         * this space here. However, with the current design, this is actually quite a good
5988
2665
         * is that rsyslog will terminate if we can not register our built-in config commands.
5989
2666
         * This, I think, is the right thing to do. -- rgerhards, 2007-07-31
5990
2667
         */
5991
 
#ifdef  USE_PTHREADS
5992
 
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize));
5993
 
#endif
5994
 
        CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs));
5995
 
        CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp));
5996
 
        CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL));
5997
 
        CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar));
5998
 
        CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv));
5999
 
        CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs));
6000
 
        CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF));
6001
 
        CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_TEMPLATE));
6002
 
        CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_OUTCHANNEL));
6003
 
        CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_ALLOWEDSENDER));
6004
 
        CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, doModLoad, NULL));
6005
 
        CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler, doIncludeLine, NULL));
6006
 
        CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, setUmask, NULL));
6007
 
        CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintTemplateList));
6008
 
        CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintModuleList));
 
2668
        CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
 
2669
        CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
 
2670
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszMainMsgQFName, NULL));
 
2671
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize, NULL));
 
2672
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQHighWtrMark, NULL));
 
2673
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQLowWtrMark, NULL));
 
2674
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt, NULL, &iMainMsgQDiscardMark, NULL));
 
2675
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity, NULL, &iMainMsgQDiscardSeverity, NULL));
 
2676
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt, NULL, &iMainMsgQPersistUpdCnt, NULL));
 
2677
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord, setMainMsgQueType, NULL, NULL));
 
2678
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrInt, NULL, &iMainMsgQueueNumWorkers, NULL));
 
2679
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoQShutdown, NULL));
 
2680
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL, &iMainMsgQtoActShutdown, NULL));
 
2681
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL, &iMainMsgQtoEnq, NULL));
 
2682
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworketimeoutrthreadshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoWrkShutdown, NULL));
 
2683
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &iMainMsgQDeqSlowdown, NULL));
 
2684
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL, &iMainMsgQWrkMinMsgs, NULL));
 
2685
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxFileSize, NULL));
 
2686
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxDiskSpace, NULL));
 
2687
        CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL));
 
2688
        CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL));
 
2689
        CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL));
 
2690
        CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
 
2691
        CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
 
2692
        CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
 
2693
        CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
 
2694
        CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
 
2695
        CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
 
2696
        CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
 
2697
        CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_ALLOWEDSENDER, NULL));
 
2698
        CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, conf.doModLoad, NULL, NULL));
 
2699
        CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler, conf.doIncludeLine, NULL, NULL));
 
2700
        CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, setUmask, NULL, NULL));
 
2701
        CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintTemplateList, NULL));
 
2702
        CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintModuleList, NULL));
6009
2703
        CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
6010
 
                 NULL, &bDebugPrintCfSysLineHandlerList));
6011
 
        CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord, NULL, &pModDir));
6012
 
        CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL));
 
2704
                 NULL, &bDebugPrintCfSysLineHandlerList, NULL));
 
2705
        CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord, NULL, &pModDir, NULL));
 
2706
        CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
 
2707
 
 
2708
        /* now add other modules handlers (we should work on that to be able to do it in ClassInit(), but so far
 
2709
         * that is not possible). -- rgerhards, 2008-01-28
 
2710
         */
 
2711
        CHKiRet(actionAddCfSysLineHdrl());
6013
2712
 
6014
2713
finalize_it:
6015
 
        return iRet;
 
2714
        RETiRet;
6016
2715
}
6017
2716
 
6018
2717
 
6022
2721
{
6023
2722
        printf("rsyslogd %s, ", VERSION);
6024
2723
        printf("compiled with:\n");
6025
 
#ifdef USE_PTHREADS
6026
 
        printf("\tFEATURE_PTHREADS (dual-threading):\tYes\n");
6027
 
#else
6028
 
        printf("\tFEATURE_PTHREADS (dual-threading):\tNo\n");
6029
 
#endif
6030
2724
#ifdef FEATURE_REGEXP
6031
2725
        printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
6032
2726
#else
6042
2736
#else
6043
2737
        printf("\tFEATURE_NETZIP (message compression):\tNo\n");
6044
2738
#endif
6045
 
#ifdef  SYSLOG_INET
6046
 
        printf("\tSYSLOG_INET (Internet/remote support):\tYes\n");
 
2739
#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
 
2740
        printf("\tGSSAPI Kerberos 5 support:\t\tYes\n");
6047
2741
#else
6048
 
        printf("\tSYSLOG_INET (Internet/remote support):\tNo\n");
 
2742
        printf("\tGSSAPI Kerberos 5 support:\t\tNo\n");
6049
2743
#endif
6050
2744
#ifndef NDEBUG
6051
2745
        printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
6052
2746
#else
6053
2747
        printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
6054
2748
#endif
 
2749
#ifdef  RTINST
 
2750
        printf("\tRuntime Instrumentation (slow code):\tYes\n");
 
2751
#else
 
2752
        printf("\tRuntime Instrumentation (slow code):\tNo\n");
 
2753
#endif
6055
2754
        printf("\nSee http://www.rsyslog.com for more information.\n");
6056
2755
}
6057
2756
 
6062
2761
 */
6063
2762
static void mainThread()
6064
2763
{
6065
 
        DEFiRet;
 
2764
        BEGINfunc
6066
2765
        uchar *pTmp;
6067
2766
 
 
2767
#if 0 // code moved back to main()
6068
2768
        /* doing some core initializations */
6069
2769
        if((iRet = modInitIminternal()) != RS_RET_OK) {
6070
2770
                fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
6077
2777
                        iRet);
6078
2778
                exit(1); /* "good" exit, leaving at init for fatal error */
6079
2779
        }
 
2780
#endif
6080
2781
 
6081
2782
        /* Note: signals MUST be processed by the thread this code is running in. The reason
6082
2783
         * is that we need to interrupt the select() system call. -- rgerhards, 2007-10-17
6083
2784
         */
6084
2785
 
6085
 
        /* initialize the default templates
6086
 
         * we use template names with a SP in front - these 
6087
 
         * can NOT be generated via the configuration file
6088
 
         */
6089
 
        pTmp = template_TraditionalFormat;
6090
 
        tplAddLine(" TradFmt", &pTmp);
 
2786
        /* initialize the build-in templates */
 
2787
        pTmp = template_SyslogProtocol23Format;
 
2788
        tplAddLine("RSYSLOG_SyslogProtocol23Format", &pTmp);
 
2789
        pTmp = template_FileFormat; /* new format for files with high-precision stamp */
 
2790
        tplAddLine("RSYSLOG_FileFormat", &pTmp);
 
2791
        pTmp = template_TraditionalFileFormat;
 
2792
        tplAddLine("RSYSLOG_TraditionalFileFormat", &pTmp);
6091
2793
        pTmp = template_WallFmt;
6092
2794
        tplAddLine(" WallFmt", &pTmp);
6093
 
        pTmp = template_StdFwdFmt;
6094
 
        tplAddLine(" StdFwdFmt", &pTmp);
 
2795
        pTmp = template_ForwardFormat;
 
2796
        tplAddLine("RSYSLOG_ForwardFormat", &pTmp);
 
2797
        pTmp = template_TraditionalForwardFormat;
 
2798
        tplAddLine("RSYSLOG_TraditionalForwardFormat", &pTmp);
6095
2799
        pTmp = template_StdUsrMsgFmt;
6096
2800
        tplAddLine(" StdUsrMsgFmt", &pTmp);
6097
2801
        pTmp = template_StdDBFmt;
6098
 
        tplLastStaticInit(tplAddLine(" StdDBFmt", &pTmp));
 
2802
        tplAddLine(" StdDBFmt", &pTmp);
 
2803
        pTmp = template_StdPgSQLFmt;
 
2804
        tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp));
6099
2805
 
6100
2806
        dbgprintf("Starting.\n");
6101
2807
        init();
6116
2822
         */
6117
2823
 
6118
2824
        mainloop();
6119
 
 
6120
 
        /* do any de-init's that need to be done AFTER this comment */
6121
 
        die(bFinished);
6122
 
}
 
2825
        ENDfunc
 
2826
}
 
2827
 
 
2828
 
 
2829
/* Method to initialize all global classes.
 
2830
 * rgerhards, 2008-01-04
 
2831
 */
 
2832
static rsRetVal
 
2833
InitGlobalClasses(void)
 
2834
{
 
2835
        DEFiRet;
 
2836
 
 
2837
        CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
 
2838
        CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
 
2839
        /* the following classes were intialized by objClassInit() */
 
2840
        CHKiRet(objUse(errmsg,   CORE_COMPONENT));
 
2841
        CHKiRet(objUse(module,   CORE_COMPONENT));
 
2842
        CHKiRet(objUse(var,      CORE_COMPONENT));
 
2843
 
 
2844
        /* initialize and use classes. We must be very careful with the order of events. Some
 
2845
         * classes use others and if we do not initialize them in the right order, we may end
 
2846
         * up with an invalid call. The most important thing that can happen is that an error
 
2847
         * is detected and needs to be logged, wich in turn requires a broader number of classes
 
2848
         * to be available. The solution is that we take care in the order of calls AND use a
 
2849
         * class immediately after it is initialized. And, of course, we load those classes
 
2850
         * first that we use ourselfs... -- rgerhards, 2008-03-07
 
2851
         */
 
2852
        CHKiRet(datetimeClassInit(NULL));
 
2853
        CHKiRet(objUse(datetime, CORE_COMPONENT));
 
2854
        CHKiRet(msgClassInit(NULL));
 
2855
        CHKiRet(strmClassInit(NULL));
 
2856
        CHKiRet(wtiClassInit(NULL));
 
2857
        CHKiRet(wtpClassInit(NULL));
 
2858
        CHKiRet(queueClassInit(NULL));
 
2859
        CHKiRet(vmstkClassInit(NULL));
 
2860
        CHKiRet(sysvarClassInit(NULL));
 
2861
        CHKiRet(vmClassInit(NULL));
 
2862
        CHKiRet(objUse(vm,       CORE_COMPONENT));
 
2863
        CHKiRet(vmopClassInit(NULL));
 
2864
        CHKiRet(vmprgClassInit(NULL));
 
2865
        CHKiRet(ctok_tokenClassInit(NULL));
 
2866
        CHKiRet(ctokClassInit(NULL));
 
2867
        CHKiRet(exprClassInit(NULL));
 
2868
        CHKiRet(objUse(expr,     CORE_COMPONENT));
 
2869
        CHKiRet(confClassInit(NULL));
 
2870
        CHKiRet(objUse(conf,     CORE_COMPONENT));
 
2871
 
 
2872
        /* dummy "classes" */
 
2873
        CHKiRet(actionClassInit());
 
2874
        CHKiRet(templateInit());
 
2875
        CHKiRet(strInit());
 
2876
 
 
2877
        /* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
 
2878
        CHKiRet(objUse(net, LM_NET_FILENAME));
 
2879
 
 
2880
finalize_it:
 
2881
        RETiRet;
 
2882
}
 
2883
 
 
2884
 
 
2885
/* Method to exit all global classes. We do not do any error checking here,
 
2886
 * because that wouldn't help us at all. So better try to deinit blindly
 
2887
 * as much as succeeds (which usually means everything will). We just must
 
2888
 * be careful to do the de-init in the opposite order of the init, because
 
2889
 * of the dependencies. However, its not as important this time, because
 
2890
 * we have reference counting.
 
2891
 * rgerhards, 2008-03-10
 
2892
 */
 
2893
static rsRetVal
 
2894
GlobalClassExit(void)
 
2895
{
 
2896
        DEFiRet;
 
2897
 
 
2898
        /* first, release everything we used ourself */
 
2899
        objRelease(net,      LM_NET_FILENAME);/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
 
2900
        objRelease(conf,     CORE_COMPONENT);
 
2901
        objRelease(expr,     CORE_COMPONENT);
 
2902
        objRelease(vm,       CORE_COMPONENT);
 
2903
        objRelease(var,      CORE_COMPONENT);
 
2904
        objRelease(datetime, CORE_COMPONENT);
 
2905
 
 
2906
        /* TODO: implement the rest of the deinit */
 
2907
        confClassExit();
 
2908
#if 0
 
2909
        CHKiRet(datetimeClassInit(NULL));
 
2910
        CHKiRet(msgClassInit(NULL));
 
2911
        CHKiRet(strmClassInit(NULL));
 
2912
        CHKiRet(wtiClassInit(NULL));
 
2913
        CHKiRet(wtpClassInit(NULL));
 
2914
        CHKiRet(queueClassInit(NULL));
 
2915
        CHKiRet(vmstkClassInit(NULL));
 
2916
        CHKiRet(sysvarClassInit(NULL));
 
2917
        CHKiRet(vmClassInit(NULL));
 
2918
        CHKiRet(vmopClassInit(NULL));
 
2919
        CHKiRet(vmprgClassInit(NULL));
 
2920
        CHKiRet(ctok_tokenClassInit(NULL));
 
2921
        CHKiRet(ctokClassInit(NULL));
 
2922
        CHKiRet(exprClassInit(NULL));
 
2923
 
 
2924
        /* dummy "classes" */
 
2925
        CHKiRet(actionClassInit());
 
2926
        CHKiRet(templateInit());
 
2927
#endif
 
2928
        /* dummy "classes */
 
2929
        strExit();
 
2930
 
 
2931
#if 0
 
2932
        CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
 
2933
        /* the following classes were intialized by objClassInit() */
 
2934
        CHKiRet(objUse(errmsg,   CORE_COMPONENT));
 
2935
        CHKiRet(objUse(module,   CORE_COMPONENT));
 
2936
#endif
 
2937
        objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
 
2938
 
 
2939
        RETiRet;
 
2940
}
 
2941
 
6123
2942
 
6124
2943
 
6125
2944
/* This is the main entry point into rsyslogd. Over time, we should try to
6126
2945
 * modularize it a bit more...
6127
2946
 */
6128
 
int main(int argc, char **argv)
 
2947
int realMain(int argc, char **argv)
6129
2948
{       
 
2949
        DEFiRet;
 
2950
 
6130
2951
        register int i;
6131
2952
        register char *p;
6132
2953
        int num_fds;
6135
2956
        extern int optind;
6136
2957
        extern char *optarg;
6137
2958
        struct sigaction sigAct;
6138
 
#if 0 /* see comment for #if 0 below (towards end of function) */
6139
 
        pthread_t thrdMain;
6140
 
        sigset_t sigSet;
6141
 
#endif
6142
 
 
6143
 
#ifdef  MTRACE
6144
 
        mtrace(); /* this is a debug aid for leak detection - either remove
6145
 
                   * or put in conditional compilation. 2005-01-18 RGerhards */
6146
 
#endif
 
2959
        int bIsFirstOption = 1;
 
2960
        int bEOptionWasGiven = 0;
 
2961
        int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
 
2962
        uchar legacyConfLine[80];
 
2963
 
 
2964
        gethostname(LocalHostName, sizeof(LocalHostName));
 
2965
        if ( (p = strchr(LocalHostName, '.')) ) {
 
2966
                *p++ = '\0';
 
2967
                LocalDomain = p;
 
2968
        }
 
2969
        else
 
2970
        {
 
2971
                LocalDomain = "";
 
2972
 
 
2973
                /* It's not clearly defined whether gethostname()
 
2974
                 * should return the simple hostname or the fqdn. A
 
2975
                 * good piece of software should be aware of both and
 
2976
                 * we want to distribute good software.  Joey
 
2977
                 *
 
2978
                 * Good software also always checks its return values...
 
2979
                 * If syslogd starts up before DNS is up & /etc/hosts
 
2980
                 * doesn't have LocalHostName listed, gethostbyname will
 
2981
                 * return NULL. 
 
2982
                 */
 
2983
                /* TODO: gethostbyname() is not thread-safe, but replacing it is
 
2984
                 * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
 
2985
                 */
 
2986
                hent = gethostbyname(LocalHostName);
 
2987
                if(hent) {
 
2988
                        snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
 
2989
                                
 
2990
                        if ( (p = strchr(LocalHostName, '.')) )
 
2991
                        {
 
2992
                                *p++ = '\0';
 
2993
                                LocalDomain = p;
 
2994
                        }
 
2995
                }
 
2996
        }
 
2997
 
 
2998
        /* Convert to lower case to recognize the correct domain laterly
 
2999
         */
 
3000
        for (p = (char *)LocalDomain; *p ; p++)
 
3001
                if (isupper((int) *p))
 
3002
                        *p = (char)tolower((int)*p);
 
3003
 
 
3004
        CHKiRet(InitGlobalClasses());
 
3005
 
 
3006
        /* doing some core initializations */
 
3007
        if((iRet = modInitIminternal()) != RS_RET_OK) {
 
3008
                fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
 
3009
                        iRet);
 
3010
                exit(1); /* "good" exit, leaving at init for fatal error */
 
3011
        }
 
3012
 
 
3013
        if((iRet = loadBuildInModules()) != RS_RET_OK) {
 
3014
                fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
 
3015
                        iRet);
 
3016
                exit(1); /* "good" exit, leaving at init for fatal error */
 
3017
        }
6147
3018
 
6148
3019
        ppid = getpid();
6149
3020
 
6150
3021
        if(chdir ("/") != 0)
6151
3022
                fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
6152
 
        for (i = 1; i < MAXFUNIX; i++) {
6153
 
                funixn[i] = "";
6154
 
                funix[i]  = -1;
6155
 
        }
6156
3023
 
6157
3024
        /* END core initializations */
6158
3025
 
6159
 
        while ((ch = getopt(argc, argv, "46Aa:dehi:f:l:m:nop:r::s:t:u:vwx")) != EOF) {
 
3026
        while ((ch = getopt(argc, argv, "46aAc:def:g:hi:l:m:M:nopqQr::s:t:u:vwx")) != EOF) {
6160
3027
                switch((char)ch) {
6161
3028
                case '4':
6162
3029
                        family = PF_INET;
6167
3034
                case 'A':
6168
3035
                        send_to_all++;
6169
3036
                        break;
6170
 
                case 'a':
6171
 
                        if (nfunix < MAXFUNIX)
6172
 
                                if(*optarg == ':') {
6173
 
                                        funixParseHost[nfunix] = 1;
6174
 
                                        funixn[nfunix++] = optarg+1;
6175
 
                                }
6176
 
                                else {
6177
 
                                        funixParseHost[nfunix] = 0;
6178
 
                                        funixn[nfunix++] = optarg;
6179
 
                                }
6180
 
                        else
6181
 
                                fprintf(stderr, "rsyslogd: Out of descriptors, ignoring %s\n", optarg);
 
3037
                case 'a':
 
3038
                        if(iCompatibilityMode < 3) {
 
3039
                                if(!bImUxSockLoaded) {
 
3040
                                        legacyOptsEnq((uchar *) "ModLoad imuxsock");
 
3041
                                        bImUxSockLoaded = 1;
 
3042
                                }
 
3043
                                snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", optarg);
 
3044
                                legacyOptsEnq(legacyConfLine);
 
3045
                        } else {
 
3046
                                fprintf(stderr, "error -a is no longer supported, use module imuxsock instead");
 
3047
                        }
 
3048
                        break;
 
3049
                case 'c':               /* compatibility mode */
 
3050
                        if(!bIsFirstOption) {
 
3051
                                fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
 
3052
                                usage();
 
3053
                                exit(1);
 
3054
                        }
 
3055
                        iCompatibilityMode = atoi(optarg);
6182
3056
                        break;
6183
3057
                case 'd':               /* debug */
6184
3058
                        Debug = 1;
6185
3059
                        break;
6186
3060
                case 'e':               /* log every message (no repeat message supression) */
6187
 
                        logEveryMsg = 1;
 
3061
                        fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
 
3062
                        bEOptionWasGiven = 1;
6188
3063
                        break;
6189
3064
                case 'f':               /* configuration file */
6190
3065
                        ConfFile = (uchar*) optarg;
6191
3066
                        break;
 
3067
                case 'g':               /* enable tcp gssapi logging */
 
3068
#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
 
3069
                        if(iCompatibilityMode < 3) {
 
3070
                                legacyOptsParseTCP(ch, optarg);
 
3071
                        } else
 
3072
                                fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n");
 
3073
#else
 
3074
                        fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
 
3075
#endif
 
3076
                        break;
6192
3077
                case 'h':
6193
 
                        NoHops = 0;
 
3078
                        if(iCompatibilityMode < 3) {
 
3079
                                errmsg.LogError(NO_ERRCODE, "WARNING: -h option is no longer supported - ignored");
 
3080
                        } else {
 
3081
                                usage(); /* for v3 and above, it simply is an error */
 
3082
                        }
6194
3083
                        break;
6195
3084
                case 'i':               /* pid file name */
6196
3085
                        PidFile = optarg;
6197
3086
                        break;
6198
3087
                case 'l':
6199
3088
                        if (LocalHosts) {
6200
 
                                fprintf (stderr, "rsyslogd: Only one -l argument allowed," \
6201
 
                                        "the first one is taken.\n");
 
3089
                                fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n");
6202
3090
                        } else {
6203
3091
                                LocalHosts = crunch_list(optarg);
6204
3092
                        }
6205
3093
                        break;
6206
3094
                case 'm':               /* mark interval */
6207
 
                        MarkInterval = atoi(optarg) * 60;
 
3095
                        if(iCompatibilityMode < 3) {
 
3096
                                MarkInterval = atoi(optarg) * 60;
 
3097
                        } else
 
3098
                                fprintf(stderr,
 
3099
                                        "-m option only supported in compatibility modes 0 to 2 - ignored\n");
 
3100
                        break;
 
3101
                case 'M': /* default module load path */
 
3102
                        module.SetModDir((uchar*)optarg);
6208
3103
                        break;
6209
3104
                case 'n':               /* don't fork */
6210
3105
                        NoFork = 1;
6211
3106
                        break;
6212
 
                case 'o':               /* omit local logging (/dev/log) */
6213
 
                        startIndexUxLocalSockets = 1;
6214
 
                        break;
6215
 
                case 'p':               /* path to regular log socket */
6216
 
                        funixn[0] = optarg;
6217
 
                        break;
 
3107
                case 'o':
 
3108
                        if(iCompatibilityMode < 3) {
 
3109
                                if(!bImUxSockLoaded) {
 
3110
                                        legacyOptsEnq((uchar *) "ModLoad imuxsock");
 
3111
                                        bImUxSockLoaded = 1;
 
3112
                                }
 
3113
                                legacyOptsEnq((uchar *) "OmitLocalLogging");
 
3114
                        } else {
 
3115
                                fprintf(stderr, "error -o is no longer supported, use module imuxsock instead");
 
3116
                        }
 
3117
                        break;
 
3118
                case 'p':
 
3119
                        if(iCompatibilityMode < 3) {
 
3120
                                if(!bImUxSockLoaded) {
 
3121
                                        legacyOptsEnq((uchar *) "ModLoad imuxsock");
 
3122
                                        bImUxSockLoaded = 1;
 
3123
                                }
 
3124
                                snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", optarg);
 
3125
                                legacyOptsEnq(legacyConfLine);
 
3126
                        } else {
 
3127
                                fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
 
3128
                        }
 
3129
                case 'q':               /* add hostname if DNS resolving has failed */
 
3130
                        *net.pACLAddHostnameOnFail = 1;
 
3131
                        break;
 
3132
                case 'Q':               /* dont resolve hostnames in ACL to IPs */
 
3133
                        *net.pACLDontResolve = 1;
 
3134
                        break;
6218
3135
                case 'r':               /* accept remote messages */
6219
3136
#ifdef SYSLOG_INET
6220
 
                        AcceptRemote = 1;
6221
 
                        if(optarg == NULL)
6222
 
                                LogPort = "0";
6223
 
                        else
6224
 
                                LogPort = optarg;
 
3137
                        if(iCompatibilityMode < 3) {
 
3138
                                legacyOptsEnq((uchar *) "ModLoad imudp");
 
3139
                                snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", optarg);
 
3140
                                legacyOptsEnq(legacyConfLine);
 
3141
                        } else
 
3142
                                fprintf(stderr,
 
3143
                                        "-r option only supported in compatibility modes 0 to 2 - ignored\n");
6225
3144
#else
6226
 
                        fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support");
 
3145
                        fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
6227
3146
#endif
6228
3147
                        break;
6229
3148
                case 's':
6230
3149
                        if (StripDomains) {
6231
 
                                fprintf (stderr, "rsyslogd: Only one -s argument allowed," \
6232
 
                                        "the first one is taken.\n");
 
3150
                                fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n");
6233
3151
                        } else {
6234
3152
                                StripDomains = crunch_list(optarg);
6235
3153
                        }
6236
3154
                        break;
6237
3155
                case 't':               /* enable tcp logging */
6238
3156
#ifdef SYSLOG_INET
6239
 
                        configureTCPListen(optarg);
 
3157
                        if(iCompatibilityMode < 3) {
 
3158
                                legacyOptsParseTCP(ch, optarg);
 
3159
                        } else
 
3160
                                fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n");
6240
3161
#else
6241
 
                        fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support");
 
3162
                        fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
6242
3163
#endif
6243
3164
                        break;
6244
3165
                case 'u':               /* misc user settings */
6258
3179
                default:
6259
3180
                        usage();
6260
3181
                }
 
3182
                bIsFirstOption = 0; /* we already saw an option character */
6261
3183
        }
6262
3184
 
6263
3185
        if ((argc -= optind))
6264
3186
                usage();
6265
3187
 
 
3188
        /* TODO: this should go away at a reasonable stage of v3 development.
 
3189
         * rgerhards, 2007-12-19
 
3190
         */
 
3191
        if(iCompatibilityMode < 3) {
 
3192
                errmsg.LogError(NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically "
 
3193
                                            "generated config directives may interfer with your rsyslog.conf settings. "
 
3194
                                            "We suggest upgrading your config and adding -c3 as the first "
 
3195
                                            "rsyslogd option.");
 
3196
                if(MarkInterval > 0) {
 
3197
                        legacyOptsEnq((uchar *) "ModLoad immark");
 
3198
                        snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "MarkMessagePeriod %d", MarkInterval);
 
3199
                        legacyOptsEnq(legacyConfLine);
 
3200
                }
 
3201
                if(!bImUxSockLoaded) {
 
3202
                        legacyOptsEnq((uchar *) "ModLoad imuxsock");
 
3203
                }
 
3204
        }
 
3205
 
 
3206
        if(bEOptionWasGiven && iCompatibilityMode < 3) {
 
3207
                errmsg.LogError(NO_ERRCODE, "WARNING: \"message repeated n times\" feature MUST be turned on in "
 
3208
                                            "rsyslog.conf - CURRENTLY EVERY MESSAGE WILL BE LOGGED. Visit "
 
3209
                                            "http://www.rsyslog.com/rptdmsgreduction to learn "
 
3210
                                            "more and cast your vote if you want us to keep this feature.");
 
3211
        }
 
3212
 
6266
3213
        checkPermissions();
 
3214
        thrdInit();
6267
3215
 
6268
3216
        if ( !(Debug || NoFork) )
6269
3217
        {
6304
3252
        else
6305
3253
                debugging_on = 1;
6306
3254
 
 
3255
        dbgprintf("Compatibility Mode: %d\n", iCompatibilityMode);
 
3256
 
6307
3257
        /* tuck my process id away */
6308
 
        if ( !Debug )
 
3258
        dbgprintf("Writing pidfile %s.\n", PidFile);
 
3259
        if (!check_pid(PidFile))
6309
3260
        {
6310
 
                dbgprintf("Writing pidfile.\n");
6311
 
                if (!check_pid(PidFile))
6312
 
                {
6313
 
                        if (!write_pid(PidFile))
6314
 
                        {
6315
 
                                fputs("Can't write pid.\n", stderr);
6316
 
                                exit(1); /* exit during startup - questionable */
6317
 
                        }
6318
 
                }
6319
 
                else
6320
 
                {
6321
 
                        fputs("Pidfile (and pid) already exist.\n", stderr);
 
3261
                if (!write_pid(PidFile))
 
3262
                {
 
3263
                        fputs("Can't write pid.\n", stderr);
6322
3264
                        exit(1); /* exit during startup - questionable */
6323
3265
                }
6324
 
        } /* if ( !Debug ) */
 
3266
        }
 
3267
        else
 
3268
        {
 
3269
                fputs("Pidfile (and pid) already exist.\n", stderr);
 
3270
                exit(1); /* exit during startup - questionable */
 
3271
        }
6325
3272
        myPid = getpid();       /* save our pid for further testing (also used for messages) */
6326
3273
 
6327
 
 
6328
 
        gethostname(LocalHostName, sizeof(LocalHostName));
6329
 
        if ( (p = strchr(LocalHostName, '.')) ) {
6330
 
                *p++ = '\0';
6331
 
                LocalDomain = p;
6332
 
        }
6333
 
        else
6334
 
        {
6335
 
                LocalDomain = "";
6336
 
 
6337
 
                /* It's not clearly defined whether gethostname()
6338
 
                 * should return the simple hostname or the fqdn. A
6339
 
                 * good piece of software should be aware of both and
6340
 
                 * we want to distribute good software.  Joey
6341
 
                 *
6342
 
                 * Good software also always checks its return values...
6343
 
                 * If syslogd starts up before DNS is up & /etc/hosts
6344
 
                 * doesn't have LocalHostName listed, gethostbyname will
6345
 
                 * return NULL. 
6346
 
                 */
6347
 
                /* TODO: gethostbyname() is not thread-safe, but replacing it is
6348
 
                 * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
6349
 
                 */
6350
 
                hent = gethostbyname(LocalHostName);
6351
 
                if(hent) {
6352
 
                        snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
6353
 
                                
6354
 
                        if ( (p = strchr(LocalHostName, '.')) )
6355
 
                        {
6356
 
                                *p++ = '\0';
6357
 
                                LocalDomain = p;
6358
 
                        }
6359
 
                }
6360
 
        }
6361
 
 
6362
 
        /* Convert to lower case to recognize the correct domain laterly
6363
 
         */
6364
 
        for (p = (char *)LocalDomain; *p ; p++)
6365
 
                if (isupper((int) *p))
6366
 
                        *p = tolower(*p);
6367
 
 
6368
3274
        memset(&sigAct, 0, sizeof (sigAct));
6369
3275
        sigemptyset(&sigAct.sa_mask);
6370
3276
 
 
3277
        sigAct.sa_handler = sigsegvHdlr;
 
3278
        sigaction(SIGSEGV, &sigAct, NULL);
 
3279
        sigAct.sa_handler = sigsegvHdlr;
 
3280
        sigaction(SIGABRT, &sigAct, NULL);
6371
3281
        sigAct.sa_handler = doDie;
6372
3282
        sigaction(SIGTERM, &sigAct, NULL);
6373
3283
        sigAct.sa_handler = Debug ? doDie : SIG_IGN;
6375
3285
        sigaction(SIGQUIT, &sigAct, NULL);
6376
3286
        sigAct.sa_handler = reapchild;
6377
3287
        sigaction(SIGCHLD, &sigAct, NULL);
6378
 
        sigAct.sa_handler = domarkAlarmHdlr;
6379
 
        sigaction(SIGALRM, &sigAct, NULL);
6380
3288
        sigAct.sa_handler = Debug ? debug_switch : SIG_IGN;
6381
3289
        sigaction(SIGUSR1, &sigAct, NULL);
6382
3290
        sigAct.sa_handler = SIG_IGN;
6383
3291
        sigaction(SIGPIPE, &sigAct, NULL);
6384
3292
        sigaction(SIGXFSZ, &sigAct, NULL); /* do not abort if 2gig file limit is hit */
6385
 
        (void) alarm(TIMERINTVL);
6386
3293
 
6387
3294
        mainThread();
6388
3295
 
6389
 
#if 0
6390
 
        /* This commented-out code was once used to spawn a separate thread
6391
 
         * for the mainThread(). This was initially done to solve a problem that not
6392
 
         * really existed. Thus the code is now commented out. I do not remove it yet,
6393
 
         * because there may be use for it in the not too distant future. If it is
6394
 
         * still commented out in a year's time, that's a good indication it should
6395
 
         * be removed!  -- rgerhards, 2007-10-17
6396
 
         */
6397
 
        i = pthread_create(&thrdMain, NULL, mainThread, NULL);
6398
 
        dbgprintf("\"main\" thread started with state %d.\n", i);
 
3296
        /* do any de-init's that need to be done AFTER this comment */
6399
3297
 
6400
 
        /* we block all signals - they will be processed by the "main"-thread. This most
6401
 
         * closely resembles previous behaviour. TODO: think about optimizing it, some
6402
 
         * signals may better be delivered here. rgerhards, 2007-10-08
6403
 
         */
6404
 
        sigfillset(&sigSet);
6405
 
        pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
 
3298
        die(bFinished);
6406
3299
        
6407
 
        /* see comment in mainThread on why we start thread and then immediately
6408
 
         * do a blocking wait on it - it makese sense... ;) rgerhards, 2007-10-08
6409
 
         */
6410
 
        pthread_join(thrdMain, NULL);
6411
 
#endif
6412
 
 
 
3300
        thrdExit();
 
3301
 
 
3302
finalize_it:
 
3303
        if(iRet != RS_RET_OK)
 
3304
                fprintf(stderr, "rsyslogd run failed with error %d.\n", iRet);
 
3305
 
 
3306
        ENDfunc
6413
3307
        return 0;
6414
3308
}
6415
3309
 
6416
3310
 
6417
 
/* vi:set ai:
 
3311
/* This is the main entry point into rsyslogd. This must be a function in its own
 
3312
 * right in order to intialize the debug system in a portable way (otherwise we would
 
3313
 * need to have a statement before variable definitions.
 
3314
 * rgerhards, 20080-01-28
 
3315
 */
 
3316
int main(int argc, char **argv)
 
3317
{       
 
3318
        dbgClassInit();
 
3319
        return realMain(argc, argv);
 
3320
}
 
3321
 
 
3322
/* vim:set ai:
6418
3323
 */