~ubuntu-branches/ubuntu/lucid/rsyslog/lucid

« back to all changes in this revision

Viewing changes to syslogd.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2007-10-19 17:21:49 UTC
  • Revision ID: james.westby@ubuntu.com-20071019172149-ie6ej2xve33mxiu7
Tags: upstream-1.19.10
ImportĀ upstreamĀ versionĀ 1.19.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * \brief This is the main file of the rsyslogd daemon.
 
3
 *
 
4
 * Please visit the rsyslog project at
 
5
 *
 
6
 * http://www.rsyslog.com
 
7
 *
 
8
 * to learn more about it and discuss any questions you may have.
 
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
 *
 
16
 * I would like to express my thanks to the developers of the sysklogd
 
17
 * package - without it, I would have had a much harder start...
 
18
 *
 
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.
 
45
 *
 
46
 * This Project was intiated and is maintained by
 
47
 * Rainer Gerhards <rgerhards@hq.adiscon.com>. See
 
48
 * AUTHORS to learn who helped make it become a reality.
 
49
 *
 
50
 * If you have questions about rsyslogd in general, please email
 
51
 * info@adiscon.com. To learn more about rsyslogd, please visit
 
52
 * http://www.rsyslog.com.
 
53
 *
 
54
 * \author Rainer Gerhards <rgerhards@adiscon.com>
 
55
 * \date 2003-10-17
 
56
 *       Some initial modifications on the sysklogd package to support
 
57
 *       liblogging. These have actually not yet been merged to the
 
58
 *       source you see currently (but they hopefully will)
 
59
 *
 
60
 * \date 2004-10-28
 
61
 *       Restarted the modifications of sysklogd. This time, we
 
62
 *       focus on a simpler approach first. The initial goal is to
 
63
 *       provide MySQL database support (so that syslogd can log
 
64
 *       to the database).
 
65
 *
 
66
 * 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,
 
75
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
76
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
77
 * GNU General Public License for more details.
 
78
 *
 
79
 * 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.
 
82
 *
 
83
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 
84
 */
 
85
#include "config.h"
 
86
#include "rsyslog.h"
 
87
 
 
88
#ifdef __FreeBSD__
 
89
#define BSD
 
90
#endif
 
91
 
 
92
/* change the following setting to e.g. 32768 if you would like to
 
93
 * support large message sizes for IHE (32k is the current maximum
 
94
 * needed for IHE). I was initially tempted to increase it to 32k,
 
95
 * but there is a large memory footprint with the current
 
96
 * implementation in rsyslog. This will change as the processing
 
97
 * changes, but I have re-set it to 1k, because the vast majority
 
98
 * of messages is below that and the memory savings is huge, at
 
99
 * least compared to the overall memory footprint.
 
100
 *
 
101
 * If you intend to receive Windows Event Log data (e.g. via
 
102
 * EventReporter - www.eventreporter.com), you might want to 
 
103
 * increase this number to an even higher value, as event
 
104
 * log messages can be very lengthy.
 
105
 * rgerhards, 2005-07-05
 
106
 *
 
107
 * during my recent testing, it showed that 4k seems to be
 
108
 * the typical maximum for UDP based syslog. This is a IP stack
 
109
 * restriction. Not always ... but very often. If you go beyond
 
110
 * that value, be sure to test that rsyslogd actually does what
 
111
 * you think it should do ;) Also, it is a good idea to check the
 
112
 * doc set for anything on IHE - it most probably has information on
 
113
 * message sizes.
 
114
 * rgerhards, 2005-08-05
 
115
 * 
 
116
 * I have increased the default message size to 2048 to be in sync
 
117
 * with recent IETF syslog standardization efforts.
 
118
 * 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
 */
 
135
#define DEFUPRI         (LOG_USER|LOG_NOTICE)
 
136
#define DEFSPRI         (LOG_KERN|LOG_CRIT)
 
137
#define TIMERINTVL      30              /* interval for checking flush, mark */
 
138
 
 
139
#define CONT_LINE       1               /* Allow continuation lines */
 
140
 
 
141
#ifdef MTRACE
 
142
#include <mcheck.h>
 
143
#endif
 
144
#include <unistd.h>
 
145
#include <stdlib.h>
 
146
#include <stdio.h>
 
147
#include <stddef.h>
 
148
#include <ctype.h>
 
149
#define GNU_SOURCE
 
150
#include <string.h>
 
151
#include <stdarg.h>
 
152
#include <time.h>
 
153
#include <dlfcn.h>
 
154
 
 
155
#include <sys/syslog.h>
 
156
#include <sys/param.h>
 
157
#ifdef  __sun
 
158
#include <errno.h>
 
159
#else
 
160
#include <sys/errno.h>
 
161
#endif
 
162
#include <sys/ioctl.h>
 
163
#include <sys/wait.h>
 
164
#include <sys/socket.h>
 
165
#include <sys/file.h>
 
166
#include <sys/un.h>
 
167
#include <sys/time.h>
 
168
#ifdef BSD
 
169
# include <sys/timespec.h>
 
170
#endif
 
171
#include <sys/resource.h>
 
172
#include <signal.h>
 
173
 
 
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>
 
184
#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
#include "srUtils.h"
 
204
#include "stringbuf.h"
 
205
#include "syslogd-types.h"
 
206
#include "template.h"
 
207
#include "outchannel.h"
 
208
#include "syslogd.h"
 
209
#include "net.h" /* struct NetAddr */
 
210
 
 
211
#include "parse.h"
 
212
#include "msg.h"
 
213
#include "modules.h"
 
214
#include "action.h"
 
215
#include "tcpsyslog.h"
 
216
#include "iminternal.h"
 
217
#include "cfsysline.h"
 
218
#include "omshell.h"
 
219
#include "omusrmsg.h"
 
220
#include "omfwd.h"
 
221
#include "omfile.h"
 
222
#include "omdiscard.h"
 
223
 
 
224
/* We define our own set of syslog defintions so that we
 
225
 * do not need to rely on (possibly different) implementations.
 
226
 * 2007-07-19 rgerhards
 
227
 */
 
228
/* missing definitions for solaris
 
229
 * 2006-02-16 Rger
 
230
 */
 
231
#ifdef __sun
 
232
#       define LOG_AUTHPRIV LOG_AUTH
 
233
#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
#define INTERNAL_NOPRI  0x10    /* the "no priority" priority */
 
238
#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
 
 
285
 
 
286
#ifndef UTMP_FILE
 
287
#ifdef UTMP_FILENAME
 
288
#define UTMP_FILE UTMP_FILENAME
 
289
#else
 
290
#ifdef _PATH_UTMP
 
291
#define UTMP_FILE _PATH_UTMP
 
292
#else
 
293
#define UTMP_FILE "/etc/utmp"
 
294
#endif
 
295
#endif
 
296
#endif
 
297
 
 
298
#ifndef _PATH_LOGCONF 
 
299
#define _PATH_LOGCONF   "/etc/rsyslog.conf"
 
300
#endif
 
301
 
 
302
#ifndef _PATH_MODDIR
 
303
#define _PATH_MODDIR    "/lib/rsyslog/"
 
304
#endif
 
305
 
 
306
#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
 
327
#endif
 
328
 
 
329
#ifndef _PATH_DEV
 
330
#define _PATH_DEV       "/dev/"
 
331
#endif
 
332
 
 
333
#ifndef _PATH_CONSOLE
 
334
#define _PATH_CONSOLE   "/dev/console"
 
335
#endif
 
336
 
 
337
#ifndef _PATH_TTY
 
338
#define _PATH_TTY       "/dev/tty"
 
339
#endif
 
340
 
 
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
static uchar    *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
 
364
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 */
 
367
 
 
368
static pid_t myPid;     /* our pid for use in self-generated messages, e.g. on startup */
 
369
/* mypid is read-only after the initial fork() */
 
370
static int debugging_on = 0; /* read-only, except on sig USR1 */
 
371
static int restart = 0; /* do restart (config read) - multithread safe */
 
372
 
 
373
static int bRequestDoMark = 0; /* do mark processing? (multithread safe) */
 
374
#define MAXFUNIX        20
 
375
 
 
376
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 */
 
429
 
 
430
static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
 
431
                                      * parsed inside message - rgerhards, 2006-03-13 */
 
432
static int bFinished = 0;       /* used by termination signal handler, read-only except there
 
433
                                 * is either 0 or the number of the signal that requested the
 
434
                                 * termination.
 
435
                                 */
 
436
 
 
437
/*
 
438
 * Intervals at which we flush out "message repeated" messages,
 
439
 * in seconds after previous message is logged.  After each flush,
 
440
 * we move to the next interval until we reach the largest.
 
441
 */
 
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
 
458
 
 
459
#define LIST_DELIMITER  ':'             /* delimiter between two hosts */
 
460
 
 
461
struct  filed *Files = NULL; /* read-only after init() (but beware of sigusr1!) */
 
462
 
 
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
static pid_t ppid; /* This is a quick and dirty hack used for spliting main/startup thread */
 
514
 
 
515
/* global variables for config file state */
 
516
static int      bDropTrailingLF = 1; /* drop trailing LF's on reception? */
 
517
int     Debug;          /* debug flag  - read-only after startup */
 
518
static int      bDebugPrintTemplateList = 1;/* output template list in debug mode? */
 
519
static int      bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
 
520
static int      bDebugPrintModuleList = 1;/* output module list in debug mode? */
 
521
int     bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
 
522
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
                                 */
 
530
/* end global config file state variables */
 
531
 
 
532
static unsigned int Forwarding = 0;
 
533
static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
 
534
char    LocalHostName[MAXHOSTNAMELEN+1];/* our hostname  - read-only after startup */
 
535
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 */
 
540
int      family = PF_UNSPEC;     /* protocol family (IPv4, IPv6 or both), set via cmdline */
 
541
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
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
int     DisableDNS = 0; /* don't look up IP addresses of remote messages */
 
546
char    **StripDomains = NULL;/* these domains may be stripped before writing logs  - r/o after s.u., never touched by init */
 
547
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
                                 */
 
561
 
 
562
extern  int errno;
 
563
 
 
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 */
 
609
 
 
610
 
 
611
/* support for simple textual representation of FIOP names
 
612
 * rgerhards, 2005-09-27
 
613
 */
 
614
static char* getFIOPName(unsigned iFIOP)
 
615
{
 
616
        char *pRet;
 
617
        switch(iFIOP) {
 
618
                case FIOP_CONTAINS:
 
619
                        pRet = "contains";
 
620
                        break;
 
621
                case FIOP_ISEQUAL:
 
622
                        pRet = "isequal";
 
623
                        break;
 
624
                case FIOP_STARTSWITH:
 
625
                        pRet = "startswith";
 
626
                        break;
 
627
                case FIOP_REGEX:
 
628
                        pRet = "regex";
 
629
                        break;
 
630
                default:
 
631
                        pRet = "NOP";
 
632
                        break;
 
633
        }
 
634
        return pRet;
 
635
}
 
636
 
 
637
 
 
638
/* Reset config variables to default values.
 
639
 * rgerhards, 2007-07-17
 
640
 */
 
641
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
 
642
{
 
643
        cCCEscapeChar = '#';
 
644
        bActExecWhenPrevSusp = 0;
 
645
        bDebugPrintTemplateList = 1;
 
646
        bDebugPrintCfSysLineHandlerList = 1;
 
647
        bDebugPrintModuleList = 1;
 
648
        bEscapeCCOnRcv = 1; /* default is to escape control characters */
 
649
        bReduceRepeatMsgs = (logEveryMsg == 1) ? 0 : 1;
 
650
        bDropMalPTRMsgs = 0;
 
651
        if(pModDir != NULL) {
 
652
                free(pModDir);
 
653
                pModDir = NULL;
 
654
        }
 
655
#ifdef USE_PTHREADS
 
656
        iMainMsgQueueSize = 10000;
 
657
#endif
 
658
 
 
659
        return RS_RET_OK;
 
660
}
 
661
 
 
662
 
 
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
 
 
676
int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
 
677
 
 
678
 
 
679
/* hardcoded standard templates (used for defaults) */
 
680
static uchar template_TraditionalFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
 
681
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%\"";
 
683
static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
 
684
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";
 
685
/* end template */
 
686
 
 
687
 
 
688
/* 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
/* Function prototypes. */
 
694
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
static void reapchild();
 
699
static void debug_switch();
 
700
static rsRetVal cfline(uchar *line, selector_t **pfCurr);
 
701
static int decode(uchar *name, struct code *codetab);
 
702
static void sighup_handler();
 
703
static void die(int sig);
 
704
static void freeSelectors(void);
 
705
static rsRetVal processConfFile(uchar *pConfFile);
 
706
static rsRetVal selectorAddList(selector_t *f);
 
707
static void processImInternal(void);
 
708
 
 
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
 
 
1636
static int usage(void)
 
1637
{
 
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");
 
1640
        exit(1); /* "good" exit - done to terminate usage() */
 
1641
}
 
1642
 
 
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
 
 
1836
/* function to destruct a selector_t object
 
1837
 * rgerhards, 2007-08-01
 
1838
 */
 
1839
static rsRetVal selectorDestruct(void *pVal)
 
1840
{
 
1841
        selector_t *pThis = (selector_t *) pVal;
 
1842
 
 
1843
        assert(pThis != NULL);
 
1844
 
 
1845
        if(pThis->pCSHostnameComp != NULL)
 
1846
                rsCStrDestruct(pThis->pCSHostnameComp);
 
1847
        if(pThis->pCSProgNameComp != NULL)
 
1848
                rsCStrDestruct(pThis->pCSProgNameComp);
 
1849
 
 
1850
        if(pThis->f_filter_type == FILTER_PROP) {
 
1851
                if(pThis->f_filterData.prop.pCSPropName != NULL)
 
1852
                        rsCStrDestruct(pThis->f_filterData.prop.pCSPropName);
 
1853
                if(pThis->f_filterData.prop.pCSCompValue != NULL)
 
1854
                        rsCStrDestruct(pThis->f_filterData.prop.pCSCompValue);
 
1855
        }
 
1856
 
 
1857
        llDestroy(&pThis->llActList);
 
1858
        free(pThis);
 
1859
        
 
1860
        return RS_RET_OK;
 
1861
}
 
1862
 
 
1863
 
 
1864
/* function to construct a selector_t object
 
1865
 * rgerhards, 2007-08-01
 
1866
 */
 
1867
static rsRetVal selectorConstruct(selector_t **ppThis)
 
1868
{
 
1869
        DEFiRet;
 
1870
        selector_t *pThis;
 
1871
 
 
1872
        assert(ppThis != NULL);
 
1873
        
 
1874
        if((pThis = (selector_t*) calloc(1, sizeof(selector_t))) == NULL) {
 
1875
                glblHadMemShortage = 1;
 
1876
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
 
1877
        }
 
1878
        CHKiRet(llInit(&pThis->llActList, actionDestruct, NULL, NULL));
 
1879
 
 
1880
finalize_it:
 
1881
        if(iRet != RS_RET_OK) {
 
1882
                if(pThis != NULL) {
 
1883
                        selectorDestruct(pThis);
 
1884
                }
 
1885
        }
 
1886
        *ppThis = pThis;
 
1887
        return iRet;
 
1888
}
 
1889
 
 
1890
 
 
1891
/* rgerhards, 2005-10-24: crunch_list is called only during option processing. So
 
1892
 * it is never called once rsyslogd is running (not even when HUPed). This code
 
1893
 * contains some exits, but they are considered safe because they only happen
 
1894
 * during startup. Anyhow, when we review the code here, we might want to
 
1895
 * reconsider the exit()s.
 
1896
 */
 
1897
static char **crunch_list(char *list)
 
1898
{
 
1899
        int count, i;
 
1900
        char *p, *q;
 
1901
        char **result = NULL;
 
1902
 
 
1903
        p = list;
 
1904
        
 
1905
        /* strip off trailing delimiters */
 
1906
        while (p[strlen(p)-1] == LIST_DELIMITER) {
 
1907
                count--;
 
1908
                p[strlen(p)-1] = '\0';
 
1909
        }
 
1910
        /* cut off leading delimiters */
 
1911
        while (p[0] == LIST_DELIMITER) {
 
1912
                count--;
 
1913
                p++; 
 
1914
        }
 
1915
        
 
1916
        /* count delimiters to calculate elements */
 
1917
        for (count=i=0; p[i]; i++)
 
1918
                if (p[i] == LIST_DELIMITER) count++;
 
1919
        
 
1920
        if ((result = (char **)malloc(sizeof(char *) * (count+2))) == NULL) {
 
1921
                printf ("Sorry, can't get enough memory, exiting.\n");
 
1922
                exit(0); /* safe exit, because only called during startup */
 
1923
        }
 
1924
        
 
1925
        /*
 
1926
         * We now can assume that the first and last
 
1927
         * characters are different from any delimiters,
 
1928
         * so we don't have to care about this.
 
1929
         */
 
1930
        count = 0;
 
1931
        while ((q=strchr(p, LIST_DELIMITER))) {
 
1932
                result[count] = (char *) malloc((q - p + 1) * sizeof(char));
 
1933
                if (result[count] == NULL) {
 
1934
                        printf ("Sorry, can't get enough memory, exiting.\n");
 
1935
                        exit(0); /* safe exit, because only called during startup */
 
1936
                }
 
1937
                strncpy(result[count], p, q - p);
 
1938
                result[count][q - p] = '\0';
 
1939
                p = q; p++;
 
1940
                count++;
 
1941
        }
 
1942
        if ((result[count] = \
 
1943
             (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) {
 
1944
                printf ("Sorry, can't get enough memory, exiting.\n");
 
1945
                exit(0); /* safe exit, because only called during startup */
 
1946
        }
 
1947
        strcpy(result[count],p);
 
1948
        result[++count] = NULL;
 
1949
 
 
1950
#if 0
 
1951
        count=0;
 
1952
        while (result[count])
 
1953
                dbgprintf("#%d: %s\n", count, StripDomains[count++]);
 
1954
#endif
 
1955
        return result;
 
1956
}
 
1957
 
 
1958
 
 
1959
void untty(void)
 
1960
#ifdef HAVE_SETSID
 
1961
{
 
1962
        if ( !Debug ) {
 
1963
                setsid();
 
1964
        }
 
1965
        return;
 
1966
}
 
1967
#else
 
1968
{
 
1969
        int i;
 
1970
 
 
1971
        if ( !Debug ) {
 
1972
                i = open(_PATH_TTY, O_RDWR);
 
1973
                if (i >= 0) {
 
1974
                        (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
 
1975
                        (void) close(i);
 
1976
                }
 
1977
        }
 
1978
}
 
1979
#endif
 
1980
 
 
1981
 
 
1982
/* rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
 
1983
 * it tried to reassemble multi-part messages, which is a legacy stock
 
1984
 * sysklogd concept. In essence, that was that messages not ending with
 
1985
 * \0 were glued together. As far as I can see, this is a sysklogd
 
1986
 * specific feature and, from looking at the code, seems to be used
 
1987
 * pretty seldom (if at all). I remove this now, not the least because it is totally
 
1988
 * incompatible with upcoming IETF syslog standards. If you experience
 
1989
 * strange behaviour with messages beeing split across multiple lines,
 
1990
 * this function here might be the place to look at.
 
1991
 *
 
1992
 * Some previous history worth noting:
 
1993
 * I added the "iSource" parameter. This is needed to distinguish between
 
1994
 * messages that have a hostname in them (received from the internet) and
 
1995
 * those that do not have (most prominently /dev/log).  rgerhards 2004-11-16
 
1996
 * And now I removed the "iSource" parameter and changed it to be "bParseHost",
 
1997
 * because all that it actually controls is whether the host is parsed or not.
 
1998
 * For rfc3195 support, we needed to modify the algo for host parsing, so we can
 
1999
 * no longer rely just on the source (rfc3195d forwarded messages arrive via
 
2000
 * unix domain sockets but contain the hostname). rgerhards, 2005-10-06
 
2001
 */
 
2002
void printchopped(char *hname, char *msg, int len, int fd, int bParseHost)
 
2003
{
 
2004
        register int iMsg;
 
2005
        char *pMsg;
 
2006
        char *pData;
 
2007
        char *pEnd;
 
2008
        char tmpline[MAXLINE + 1];
 
2009
#       ifdef USE_NETZIP
 
2010
        char deflateBuf[MAXLINE + 1];
 
2011
        uLongf iLenDefBuf;
 
2012
#       endif
 
2013
 
 
2014
        assert(hname != NULL);
 
2015
        assert(msg != NULL);
 
2016
        assert(len >= 0);
 
2017
 
 
2018
        dbgprintf("Message length: %d, File descriptor: %d.\n", len, fd);
 
2019
 
 
2020
        /* we first check if we have a NUL character at the very end of the
 
2021
         * message. This seems to be a frequent problem with a number of senders.
 
2022
         * So I have now decided to drop these NULs. However, if they are intentional,
 
2023
         * that may cause us some problems, e.g. with syslog-sign. On the other hand,
 
2024
         * current code always has problems with intentional NULs (as it needs to escape
 
2025
         * them to prevent problems with the C string libraries), so that does not
 
2026
         * really matter. Just to be on the save side, we'll log destruction of such
 
2027
         * NULs in the debug log.
 
2028
         * rgerhards, 2007-09-14
 
2029
         */
 
2030
        if(*(msg + len - 1) == '\0') {
 
2031
                dbgprintf("dropped NUL at very end of message\n");
 
2032
                len--;
 
2033
        }
 
2034
 
 
2035
        /* then we check if we need to drop trailing LFs, which often make
 
2036
         * their way into syslog messages unintentionally. In order to remain
 
2037
         * compatible to recent IETF developments, we allow the user to
 
2038
         * turn on/off this handling.  rgerhards, 2007-07-23
 
2039
         */
 
2040
        if(bDropTrailingLF && *(msg + len - 1) == '\n') {
 
2041
                dbgprintf("dropped LF at very end of message (DropTrailingLF is set)\n");
 
2042
                len--;
 
2043
        }
 
2044
 
 
2045
        iMsg = 0;       /* initialize receiving buffer index */
 
2046
        pMsg = tmpline; /* set receiving buffer pointer */
 
2047
        pData = msg;    /* set source buffer pointer */
 
2048
        pEnd = msg + len; /* this is one off, which is intensional */
 
2049
 
 
2050
#       ifdef USE_NETZIP
 
2051
        /* we first need to check if we have a compressed record. If so,
 
2052
         * we must decompress it.
 
2053
         */
 
2054
        if(len > 0 && *msg == 'z') { /* compressed data present? (do NOT change order if conditions!) */
 
2055
                /* we have compressed data, so let's deflate it. We support a maximum
 
2056
                 * message size of MAXLINE. If it is larger, an error message is logged
 
2057
                 * and the message is dropped. We do NOT try to decompress larger messages
 
2058
                 * as such might be used for denial of service. It might happen to later
 
2059
                 * builds that such functionality be added as an optional, operator-configurable
 
2060
                 * feature.
 
2061
                 */
 
2062
                int ret;
 
2063
                iLenDefBuf = MAXLINE;
 
2064
                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);
 
2067
                /* Now check if the uncompression worked. If not, there is not much we can do. In
 
2068
                 * that case, we log an error message but ignore the message itself. Storing the
 
2069
                 * compressed text is dangerous, as it contains control characters. So we do
 
2070
                 * not do this. If someone would like to have a copy, this code here could be
 
2071
                 * modified to do a hex-dump of the buffer in question. We do not include
 
2072
                 * this functionality right now.
 
2073
                 * rgerhards, 2006-12-07
 
2074
                 */
 
2075
                if(ret != Z_OK) {
 
2076
                        logerrorInt("Uncompression of a message failed with return code %d "
 
2077
                                    "- enable debug logging if you need further information. "
 
2078
                                    "Message ignored.", ret);
 
2079
                        return; /* unconditional exit, nothing left to do... */
 
2080
                }
 
2081
                pData = deflateBuf;
 
2082
                pEnd = deflateBuf + iLenDefBuf;
 
2083
        }
 
2084
#       else /* ifdef USE_NETZIP */
 
2085
        /* in this case, we still need to check if the message is compressed. If so, we must
 
2086
         * tell the user we can not accept it.
 
2087
         */
 
2088
        if(len > 0 && *msg == 'z') {
 
2089
                logerror("Received a compressed message, but rsyslogd does not have compression "
 
2090
                         "support enabled. The message will be ignored.");
 
2091
                return;
 
2092
        }       
 
2093
#       endif /* ifdef USE_NETZIP */
 
2094
 
 
2095
        while(pData < pEnd) {
 
2096
                if(iMsg >= MAXLINE) {
 
2097
                        /* emergency, we now need to flush, no matter if
 
2098
                         * we are at end of message or not...
 
2099
                         */
 
2100
                        if(iMsg == MAXLINE) {
 
2101
                                *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
 
2102
                                printline(hname, tmpline, bParseHost);
 
2103
                        } else {
 
2104
                                /* This case in theory never can happen. If it happens, we have
 
2105
                                 * a logic error. I am checking for it, because if I would not,
 
2106
                                 * we would address memory invalidly with the code above. I
 
2107
                                 * do not care much about this case, just a debug log entry
 
2108
                                 * (I couldn't do any more smart things anyway...).
 
2109
                                 * rgerhards, 2007-9-20
 
2110
                                 */
 
2111
                                dbgprintf("internal error: iMsg > MAXLINE in printchopped()\n");
 
2112
                        }
 
2113
                        return; /* in this case, we are done... nothing left we can do */
 
2114
                }
 
2115
                if(*pData == '\0') { /* guard against \0 characters... */
 
2116
                        /* changed to the sequence (somewhat) proposed in
 
2117
                         * draft-ietf-syslog-protocol-19. rgerhards, 2006-11-30
 
2118
                         */
 
2119
                        if(iMsg + 3 < MAXLINE) { /* do we have space? */
 
2120
                                *(pMsg + iMsg++) =  cCCEscapeChar;
 
2121
                                *(pMsg + iMsg++) = '0';
 
2122
                                *(pMsg + iMsg++) = '0';
 
2123
                                *(pMsg + iMsg++) = '0';
 
2124
                        } /* if we do not have space, we simply ignore the '\0'... */
 
2125
                          /* log an error? Very questionable... rgerhards, 2006-11-30 */
 
2126
                          /* decided: we do not log an error, it won't help... rger, 2007-06-21 */
 
2127
                        ++pData;
 
2128
                } else if(bEscapeCCOnRcv && iscntrl((int) *pData)) {
 
2129
                        /* we are configured to escape control characters. Please note
 
2130
                         * that this most probably break non-western character sets like
 
2131
                         * Japanese, Korean or Chinese. rgerhards, 2007-07-17
 
2132
                         * Note: sysklogd logs octal values only for DEL and CCs above 127.
 
2133
                         * For others, it logs ^n where n is the control char converted to an
 
2134
                         * alphabet character. We like consistency and thus escape it to octal
 
2135
                         * in all cases. If someone complains, we may change the mode. At least
 
2136
                         * we known now what's going on.
 
2137
                         * rgerhards, 2007-07-17
 
2138
                         */
 
2139
                        if(iMsg + 3 < MAXLINE) { /* do we have space? */
 
2140
                                *(pMsg + iMsg++) = cCCEscapeChar;
 
2141
                                *(pMsg + iMsg++) = '0' + ((*pData & 0300) >> 6);
 
2142
                                *(pMsg + iMsg++) = '0' + ((*pData & 0070) >> 3);
 
2143
                                *(pMsg + iMsg++) = '0' + ((*pData & 0007));
 
2144
                        } /* again, if we do not have space, we ignore the char - see comment at '\0' */
 
2145
                        ++pData;
 
2146
                } else {
 
2147
                        *(pMsg + iMsg++) = *pData++;
 
2148
                }
 
2149
        }
 
2150
 
 
2151
        *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
 
2152
 
 
2153
        /* 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;
 
2237
 
 
2238
/* rgerhards 2004-11-09: the following is a function that can be used
 
2239
 * to log a message orginating from the syslogd itself. In sysklogd code,
 
2240
 * this is done by simply calling logmsg(). However, logmsg() is changed in
 
2241
 * rsyslog so that it takes a msg "object". So it can no longer be called
 
2242
 * directly. This method here solves the need. It provides an interface that
 
2243
 * allows to construct a locally-generated message. Please note that this
 
2244
 * function here probably is only an interim solution and that we need to
 
2245
 * think on the best way to do this.
 
2246
 */
 
2247
static void logmsgInternal(int pri, char *msg, int flags)
 
2248
{
 
2249
        msg_t *pMsg;
 
2250
 
 
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
 
 
2269
        MsgSetUxTradMsg(pMsg, msg);
 
2270
        MsgSetRawMsg(pMsg, msg);
 
2271
        MsgSetHOSTNAME(pMsg, LocalHostName);
 
2272
        MsgSetTAG(pMsg, "rsyslogd:");
 
2273
        pMsg->iFacility = LOG_FAC(pri);
 
2274
        pMsg->iSeverity = LOG_PRI(pri);
 
2275
        pMsg->bParseHOSTNAME = 0;
 
2276
        getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
2277
        flags |= INTERNAL_MSG;
 
2278
 
 
2279
#ifdef USE_PTHREADS
 
2280
        if(bRunningMultithreaded == 0) { /* not yet in queued mode */
 
2281
                iminternalAddMsg(pri, pMsg, flags);
 
2282
        } else {
 
2283
                /* we have the queue, so we can simply provide the 
 
2284
                 * message to the queue engine.
 
2285
                 */
 
2286
                logmsg(pri, pMsg, flags);
 
2287
                MsgDestruct(pMsg);
 
2288
        }
 
2289
#else
 
2290
        iminternalAddMsg(pri, pMsg, flags);
 
2291
#endif
 
2292
}
 
2293
 
 
2294
/* This functions looks at the given message and checks if it matches the
 
2295
 * provided filter condition. If so, it returns true, else it returns
 
2296
 * false. This is a helper to logmsg() and meant to drive the decision
 
2297
 * process if a message is to be processed or not. As I expect this
 
2298
 * decision code to grow more complex over time AND logmsg() is already
 
2299
 * a very lengthy function, I thought a separate function is more appropriate.
 
2300
 * 2005-09-19 rgerhards
 
2301
 */
 
2302
int shouldProcessThisMessage(selector_t *f, msg_t *pMsg)
 
2303
{
 
2304
        unsigned short pbMustBeFreed;
 
2305
        char *pszPropVal;
 
2306
        int iRet = 0;
 
2307
 
 
2308
        assert(f != NULL);
 
2309
        assert(pMsg != NULL);
 
2310
 
 
2311
        /* we first have a look at the global, BSD-style block filters (for tag
 
2312
         * and host). Only if they match, we evaluate the actual filter.
 
2313
         * rgerhards, 2005-10-18
 
2314
         */
 
2315
        if(f->eHostnameCmpMode == HN_NO_COMP) {
 
2316
                /* EMPTY BY INTENSION - we check this value first, because
 
2317
                 * it is the one most often used, so this saves us time!
 
2318
                 */
 
2319
        } else if(f->eHostnameCmpMode == HN_COMP_MATCH) {
 
2320
                if(rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
 
2321
                        /* not equal, so we are already done... */
 
2322
                        dbgprintf("hostname filter '+%s' does not match '%s'\n", 
 
2323
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
 
2324
                        return 0;
 
2325
                }
 
2326
        } else { /* must be -hostname */
 
2327
                if(!rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
 
2328
                        /* not equal, so we are already done... */
 
2329
                        dbgprintf("hostname filter '-%s' does not match '%s'\n", 
 
2330
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
 
2331
                        return 0;
 
2332
                }
 
2333
        }
 
2334
        
 
2335
        if(f->pCSProgNameComp != NULL) {
 
2336
                int bInv = 0, bEqv = 0, offset = 0;
 
2337
                if(*(rsCStrGetSzStrNoNULL(f->pCSProgNameComp)) == '-') {
 
2338
                        if(*(rsCStrGetSzStrNoNULL(f->pCSProgNameComp) + 1) == '-')
 
2339
                                offset = 1;
 
2340
                        else {
 
2341
                                bInv = 1;
 
2342
                                offset = 1;
 
2343
                        }
 
2344
                }
 
2345
                if(!rsCStrOffsetSzStrCmp(f->pCSProgNameComp, offset, (uchar*) getProgramName(pMsg), getProgramNameLen(pMsg)))
 
2346
                        bEqv = 1;
 
2347
 
 
2348
                if((!bEqv && !bInv) || (bEqv && bInv)) {
 
2349
                        /* not equal or inverted selection, so we are already done... */
 
2350
                        dbgprintf("programname filter '%s' does not match '%s'\n", 
 
2351
                                rsCStrGetSzStrNoNULL(f->pCSProgNameComp), getProgramName(pMsg));
 
2352
                        return 0;
 
2353
                }
 
2354
        }
 
2355
        
 
2356
        /* done with the BSD-style block filters */
 
2357
 
 
2358
        if(f->f_filter_type == FILTER_PRI) {
 
2359
                /* skip messages that are incorrect priority */
 
2360
                if ( (f->f_filterData.f_pmask[pMsg->iFacility] == TABLE_NOPRI) || \
 
2361
                    ((f->f_filterData.f_pmask[pMsg->iFacility] & (1<<pMsg->iSeverity)) == 0) )
 
2362
                        iRet = 0;
 
2363
                else
 
2364
                        iRet = 1;
 
2365
        } else {
 
2366
                assert(f->f_filter_type == FILTER_PROP); /* assert() just in case... */
 
2367
                pszPropVal = MsgGetProp(pMsg, NULL,
 
2368
                                f->f_filterData.prop.pCSPropName, &pbMustBeFreed);
 
2369
 
 
2370
                /* Now do the compares (short list currently ;)) */
 
2371
                switch(f->f_filterData.prop.operation ) {
 
2372
                case FIOP_CONTAINS:
 
2373
                        if(rsCStrLocateInSzStr(f->f_filterData.prop.pCSCompValue, (uchar*) pszPropVal) != -1)
 
2374
                                iRet = 1;
 
2375
                        break;
 
2376
                case FIOP_ISEQUAL:
 
2377
                        if(rsCStrSzStrCmp(f->f_filterData.prop.pCSCompValue,
 
2378
                                          (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
 
2379
                                iRet = 1; /* process message! */
 
2380
                        break;
 
2381
                case FIOP_STARTSWITH:
 
2382
                        if(rsCStrSzStrStartsWithCStr(f->f_filterData.prop.pCSCompValue,
 
2383
                                          (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
 
2384
                                iRet = 1; /* process message! */
 
2385
                        break;
 
2386
                case FIOP_REGEX:
 
2387
                        if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
 
2388
                                          (unsigned char*) pszPropVal) == 0)
 
2389
                                iRet = 1;
 
2390
                        break;
 
2391
                default:
 
2392
                        /* here, it handles NOP (for performance reasons) */
 
2393
                        assert(f->f_filterData.prop.operation == FIOP_NOP);
 
2394
                        iRet = 1; /* as good as any other default ;) */
 
2395
                        break;
 
2396
                }
 
2397
 
 
2398
                /* now check if the value must be negated */
 
2399
                if(f->f_filterData.prop.isNegated)
 
2400
                        iRet = (iRet == 1) ?  0 : 1;
 
2401
 
 
2402
                if(Debug) {
 
2403
                        printf("Filter: check for property '%s' (value '%s') ",
 
2404
                                rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName),
 
2405
                                pszPropVal);
 
2406
                        if(f->f_filterData.prop.isNegated)
 
2407
                                printf("NOT ");
 
2408
                        printf("%s '%s': %s\n",
 
2409
                               getFIOPName(f->f_filterData.prop.operation),
 
2410
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue),
 
2411
                               iRet ? "TRUE" : "FALSE");
 
2412
                }
 
2413
 
 
2414
                /* cleanup */
 
2415
                if(pbMustBeFreed)
 
2416
                        free(pszPropVal);
 
2417
        }
 
2418
 
 
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
finalize_it:
 
2513
        return iRet;
 
2514
}
 
2515
 
 
2516
 
 
2517
/* helper to processMsg(), used to call the configured actions. It is
 
2518
 * executed from within llExecFunc() of the action list.
 
2519
 * rgerhards, 2007-08-02
 
2520
 */
 
2521
typedef struct processMsgDoActions_s {
 
2522
        int bPrevWasSuspended; /* was the previous action suspended? */
 
2523
        msg_t *pMsg;
 
2524
} processMsgDoActions_t;
 
2525
DEFFUNC_llExecFunc(processMsgDoActions)
 
2526
{
 
2527
        DEFiRet;
 
2528
        rsRetVal iRetMod;       /* return value of module - we do not always pass that back */
 
2529
        action_t *pAction = (action_t*) pData;
 
2530
        processMsgDoActions_t *pDoActData = (processMsgDoActions_t*) pParam;
 
2531
 
 
2532
        assert(pAction != NULL);
 
2533
 
 
2534
        if((pAction->bExecWhenPrevSusp  == 1) && (pDoActData->bPrevWasSuspended == 0)) {
 
2535
                dbgprintf("not calling action because the previous one is not suspended\n");
 
2536
                ABORT_FINALIZE(RS_RET_OK);
 
2537
        }
 
2538
 
 
2539
        iRetMod = callAction(pDoActData->pMsg, pAction);
 
2540
        if(iRetMod == RS_RET_DISCARDMSG) {
 
2541
                ABORT_FINALIZE(RS_RET_DISCARDMSG);
 
2542
        } else if(iRetMod == RS_RET_SUSPENDED) {
 
2543
                /* indicate suspension for next module to be called */
 
2544
                pDoActData->bPrevWasSuspended = 1;
 
2545
        } else {
 
2546
                pDoActData->bPrevWasSuspended = 0;
 
2547
        }
 
2548
 
 
2549
finalize_it:
 
2550
        return iRet;
 
2551
}
 
2552
 
 
2553
 
 
2554
/* 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
 * rgerhards, 2005-10-13
 
2559
 */
 
2560
static void processMsg(msg_t *pMsg)
 
2561
{
 
2562
        selector_t *f;
 
2563
        int bContinue;
 
2564
        processMsgDoActions_t DoActData;
 
2565
 
 
2566
        assert(pMsg != NULL);
 
2567
 
 
2568
        /* log the message to the particular outputs */
 
2569
        if (!Initialized) {
 
2570
                doEmergencyLogging(pMsg);
 
2571
                return;
 
2572
        }
 
2573
 
 
2574
        bContinue = 1;
 
2575
        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)) {
 
2586
                        continue;
 
2587
                }
 
2588
 
 
2589
                /* ok -- from here, we have action-specific code, nothing really selector-specific -- rger 2007-08-01 */
 
2590
                DoActData.pMsg = pMsg;
 
2591
                DoActData.bPrevWasSuspended = 0;
 
2592
                if(llExecFunc(&f->llActList, processMsgDoActions, (void*)&DoActData) == RS_RET_DISCARDMSG)
 
2593
                        bContinue = 0;
 
2594
        }
 
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;
 
2798
 
 
2799
        assert(pMsg != NULL);
 
2800
 
 
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
        }
 
2830
}
 
2831
#endif /* #ifndef USE_PTHREADS */
 
2832
 
 
2833
 
 
2834
/* Helper to parseRFCSyslogMsg. This function parses a field up to
 
2835
 * (and including) the SP character after it. The field contents is
 
2836
 * returned in a caller-provided buffer. The parsepointer is advanced
 
2837
 * to after the terminating SP. The caller must ensure that the 
 
2838
 * provided buffer is large enough to hold the to be extracted value.
 
2839
 * Returns 0 if everything is fine or 1 if either the field is not
 
2840
 * SP-terminated or any other error occurs.
 
2841
 * rger, 2005-11-24
 
2842
 */
 
2843
static int parseRFCField(char **pp2parse, char *pResult)
 
2844
{
 
2845
        char *p2parse;
 
2846
        int iRet = 0;
 
2847
 
 
2848
        assert(pp2parse != NULL);
 
2849
        assert(*pp2parse != NULL);
 
2850
        assert(pResult != NULL);
 
2851
 
 
2852
        p2parse = *pp2parse;
 
2853
 
 
2854
        /* this is the actual parsing loop */
 
2855
        while(*p2parse && *p2parse != ' ') {
 
2856
                *pResult++ = *p2parse++;
 
2857
        }
 
2858
 
 
2859
        if(*p2parse == ' ')
 
2860
                ++p2parse; /* eat SP, but only if not at end of string */
 
2861
        else
 
2862
                iRet = 1; /* there MUST be an SP! */
 
2863
        *pResult = '\0';
 
2864
 
 
2865
        /* set the new parse pointer */
 
2866
        *pp2parse = p2parse;
 
2867
        return 0;
 
2868
}
 
2869
 
 
2870
 
 
2871
/* Helper to parseRFCSyslogMsg. This function parses the structured
 
2872
 * data field of a message. It does NOT parse inside structured data,
 
2873
 * just gets the field as whole. Parsing the single entities is left
 
2874
 * to other functions. The parsepointer is advanced
 
2875
 * to after the terminating SP. The caller must ensure that the 
 
2876
 * provided buffer is large enough to hold the to be extracted value.
 
2877
 * Returns 0 if everything is fine or 1 if either the field is not
 
2878
 * SP-terminated or any other error occurs.
 
2879
 * rger, 2005-11-24
 
2880
 */
 
2881
static int parseRFCStructuredData(char **pp2parse, char *pResult)
 
2882
{
 
2883
        char *p2parse;
 
2884
        int bCont = 1;
 
2885
        int iRet = 0;
 
2886
 
 
2887
        assert(pp2parse != NULL);
 
2888
        assert(*pp2parse != NULL);
 
2889
        assert(pResult != NULL);
 
2890
 
 
2891
        p2parse = *pp2parse;
 
2892
 
 
2893
        /* this is the actual parsing loop
 
2894
         * Remeber: structured data starts with [ and includes any characters
 
2895
         * until the first ] followed by a SP. There may be spaces inside
 
2896
         * structured data. There may also be \] inside the structured data, which
 
2897
         * do NOT terminate an element.
 
2898
         */
 
2899
        if(*p2parse != '[')
 
2900
                return 1; /* this is NOT structured data! */
 
2901
 
 
2902
        while(bCont) {
 
2903
                if(*p2parse == '\0') {
 
2904
                        iRet = 1; /* this is not valid! */
 
2905
                        bCont = 0;
 
2906
                } else if(*p2parse == '\\' && *(p2parse+1) == ']') {
 
2907
                        /* this is escaped, need to copy both */
 
2908
                        *pResult++ = *p2parse++;
 
2909
                        *pResult++ = *p2parse++;
 
2910
                } else if(*p2parse == ']' && *(p2parse+1) == ' ') {
 
2911
                        /* found end, just need to copy the ] and eat the SP */
 
2912
                        *pResult++ = *p2parse;
 
2913
                        p2parse += 2;
 
2914
                        bCont = 0;
 
2915
                } else {
 
2916
                        *pResult++ = *p2parse++;
 
2917
                }
 
2918
        }
 
2919
 
 
2920
        if(*p2parse == ' ')
 
2921
                ++p2parse; /* eat SP, but only if not at end of string */
 
2922
        else
 
2923
                iRet = 1; /* there MUST be an SP! */
 
2924
        *pResult = '\0';
 
2925
 
 
2926
        /* set the new parse pointer */
 
2927
        *pp2parse = p2parse;
 
2928
        return 0;
 
2929
}
 
2930
 
 
2931
/* parse a RFC-formatted syslog message. This function returns
 
2932
 * 0 if processing of the message shall continue and 1 if something
 
2933
 * went wrong and this messe should be ignored. This function has been
 
2934
 * implemented in the effort to support syslog-protocol. Please note that
 
2935
 * the name (parse *RFC*) stems from the hope that syslog-protocol will
 
2936
 * some time become an RFC. Do not confuse this with informational
 
2937
 * RFC 3164 (which is legacy syslog).
 
2938
 *
 
2939
 * currently supported format:
 
2940
 *
 
2941
 * <PRI>VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG
 
2942
 *
 
2943
 * <PRI> is already stripped when this function is entered. VERSION already
 
2944
 * has been confirmed to be "1", but has NOT been stripped from the message.
 
2945
 *
 
2946
 * rger, 2005-11-24
 
2947
 */
 
2948
static int parseRFCSyslogMsg(msg_t *pMsg, int flags)
 
2949
{
 
2950
        char *p2parse;
 
2951
        char *pBuf;
 
2952
        int bContParse = 1;
 
2953
 
 
2954
        assert(pMsg != NULL);
 
2955
        assert(pMsg->pszUxTradMsg != NULL);
 
2956
        p2parse = (char*) pMsg->pszUxTradMsg;
 
2957
 
 
2958
        /* do a sanity check on the version and eat it */
 
2959
        assert(p2parse[0] == '1' && p2parse[1] == ' ');
 
2960
        p2parse += 2;
 
2961
 
 
2962
        /* Now get us some memory we can use as a work buffer while parsing.
 
2963
         * We simply allocated a buffer sufficiently large to hold all of the
 
2964
         * message, so we can not run into any troubles. I think this is
 
2965
         * more wise then to use individual buffers.
 
2966
         */
 
2967
        if((pBuf = malloc(sizeof(char)* strlen(p2parse) + 1)) == NULL)
 
2968
                return 1;
 
2969
                
 
2970
        /* IMPORTANT NOTE:
 
2971
         * Validation is not actually done below nor are any errors handled. I have
 
2972
         * NOT included this for the current proof of concept. However, it is strongly
 
2973
         * advisable to add it when this code actually goes into production.
 
2974
         * rgerhards, 2005-11-24
 
2975
         */
 
2976
 
 
2977
        /* TIMESTAMP */
 
2978
        if(srSLMGParseTIMESTAMP3339(&(pMsg->tTIMESTAMP),  &p2parse) == FALSE) {
 
2979
                dbgprintf("no TIMESTAMP detected!\n");
 
2980
                bContParse = 0;
 
2981
                flags |= ADDDATE;
 
2982
        }
 
2983
 
 
2984
        if (flags & ADDDATE) {
 
2985
                getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
2986
        }
 
2987
 
 
2988
        /* HOSTNAME */
 
2989
        if(bContParse) {
 
2990
                parseRFCField(&p2parse, pBuf);
 
2991
                MsgSetHOSTNAME(pMsg, pBuf);
 
2992
        } else {
 
2993
                /* we can not parse, so we get the system we
 
2994
                 * received the data from.
 
2995
                 */
 
2996
                MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
 
2997
        }
 
2998
 
 
2999
        /* APP-NAME */
 
3000
        if(bContParse) {
 
3001
                parseRFCField(&p2parse, pBuf);
 
3002
                MsgSetAPPNAME(pMsg, pBuf);
 
3003
        }
 
3004
 
 
3005
        /* PROCID */
 
3006
        if(bContParse) {
 
3007
                parseRFCField(&p2parse, pBuf);
 
3008
                MsgSetPROCID(pMsg, pBuf);
 
3009
        }
 
3010
 
 
3011
        /* MSGID */
 
3012
        if(bContParse) {
 
3013
                parseRFCField(&p2parse, pBuf);
 
3014
                MsgSetMSGID(pMsg, pBuf);
 
3015
        }
 
3016
 
 
3017
        /* STRUCTURED-DATA */
 
3018
        if(bContParse) {
 
3019
                parseRFCStructuredData(&p2parse, pBuf);
 
3020
                MsgSetStructuredData(pMsg, pBuf);
 
3021
        }
 
3022
 
 
3023
        /* MSG */
 
3024
        MsgSetMSG(pMsg, p2parse);
 
3025
 
 
3026
        return 0; /* all ok */
 
3027
}
 
3028
/* parse a legay-formatted syslog message. This function returns
 
3029
 * 0 if processing of the message shall continue and 1 if something
 
3030
 * went wrong and this messe should be ignored. This function has been
 
3031
 * implemented in the effort to support syslog-protocol.
 
3032
 * rger, 2005-11-24
 
3033
 * As of 2006-01-10, I am removing the logic to continue parsing only
 
3034
 * when a valid TIMESTAMP is detected. Validity of other fields already
 
3035
 * is ignored. This is due to the fact that the parser has grown smarter
 
3036
 * and is now more able to understand different dialects of the syslog
 
3037
 * message format. I do not expect any bad side effects of this change,
 
3038
 * but I thought I log it in this comment.
 
3039
 * rgerhards, 2006-01-10
 
3040
 */
 
3041
static int parseLegacySyslogMsg(msg_t *pMsg, int flags)
 
3042
{
 
3043
        char *p2parse;
 
3044
        char *pBuf;
 
3045
        char *pWork;
 
3046
        rsCStrObj *pStrB;
 
3047
        int iCnt;
 
3048
        int bTAGCharDetected;
 
3049
 
 
3050
        assert(pMsg != NULL);
 
3051
        assert(pMsg->pszUxTradMsg != NULL);
 
3052
        p2parse = (char*) pMsg->pszUxTradMsg;
 
3053
 
 
3054
        /* Check to see if msg contains a timestamp
 
3055
         */
 
3056
        if(srSLMGParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
 
3057
                p2parse += 16;
 
3058
        else {
 
3059
                flags |= ADDDATE;
 
3060
        }
 
3061
 
 
3062
        /* here we need to check if the timestamp is valid. If it is not,
 
3063
         * we can not continue to parse but must treat the rest as the 
 
3064
         * MSG part of the message (as of RFC 3164).
 
3065
         * rgerhards 2004-12-03
 
3066
         */
 
3067
        (void) time(&now);
 
3068
        if (flags & ADDDATE) {
 
3069
                getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
 
3070
        }
 
3071
 
 
3072
        /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we 
 
3073
         * do this only when the user has not forbidden this. I now introduce some
 
3074
         * code that allows a user to configure rsyslogd to treat the rest of the
 
3075
         * message as MSG part completely. In this case, the hostname will be the
 
3076
         * machine that we received the message from and the tag will be empty. This
 
3077
         * is meant to be an interim solution, but for now it is in the code.
 
3078
         */
 
3079
 
 
3080
        if(bParseHOSTNAMEandTAG && !(flags & INTERNAL_MSG)) {
 
3081
                /* parse HOSTNAME - but only if this is network-received!
 
3082
                 * rger, 2005-11-14: we still have a problem with BSD messages. These messages
 
3083
                 * do NOT include a host name. In most cases, this leads to the TAG to be treated
 
3084
                 * as hostname and the first word of the message as the TAG. Clearly, this is not
 
3085
                 * of advantage ;) I think I have now found a way to handle this situation: there
 
3086
                 * are certain characters which are frequently used in TAG (e.g. ':'), which are
 
3087
                 * *invalid* in host names. So while parsing the hostname, I check for these characters.
 
3088
                 * If I find them, I set a simple flag but continue. After parsing, I check the flag.
 
3089
                 * If it was set, then we most probably do not have a hostname but a TAG. Thus, I change
 
3090
                 * the fields. I think this logic shall work with any type of syslog message.
 
3091
                 */
 
3092
                bTAGCharDetected = 0;
 
3093
                if(pMsg->bParseHOSTNAME) {
 
3094
                        /* TODO: quick and dirty memory allocation */
 
3095
                        /* the memory allocated is far too much in most cases. But on the plus side,
 
3096
                         * it is quite fast... - rgerhards, 2007-09-20
 
3097
                         */
 
3098
                        if((pBuf = malloc(sizeof(char)* (strlen(p2parse) +1))) == NULL)
 
3099
                                return 1;
 
3100
                        pWork = pBuf;
 
3101
                        /* this is the actual parsing loop */
 
3102
                        while(*p2parse && *p2parse != ' ' && *p2parse != ':') {
 
3103
                                if(*p2parse == '[' || *p2parse == ']' || *p2parse == '/')
 
3104
                                        bTAGCharDetected = 1;
 
3105
                                *pWork++ = *p2parse++;
 
3106
                        }
 
3107
                        /* we need to handle ':' seperately, because it terminates the
 
3108
                         * TAG - so we also need to terminate the parser here!
 
3109
                         * rgerhards, 2007-09-10 *p2parse points to a valid address here in 
 
3110
                         * any case. We can reach this point only if we are at end of string,
 
3111
                         * or we have a ':' or ' '. What the if below does is check if we are
 
3112
                         * not at end of string and, if so, advance the parse pointer. If we 
 
3113
                         * are already at end of string, *p2parse is equal to '\0', neither if
 
3114
                         * will be true and the parse pointer remain as is. This is perfectly
 
3115
                         * well.
 
3116
                         */
 
3117
                        if(*p2parse == ':') {
 
3118
                                bTAGCharDetected = 1;
 
3119
                                ++p2parse;
 
3120
                        } else if(*p2parse == ' ')
 
3121
                                ++p2parse;
 
3122
                        *pWork = '\0';
 
3123
                        MsgAssignHOSTNAME(pMsg, pBuf);
 
3124
                }
 
3125
                /* check if we seem to have a TAG */
 
3126
                if(bTAGCharDetected) {
 
3127
                        /* indeed, this smells like a TAG, so lets use it for this. We take
 
3128
                         * the HOSTNAME from the sender system instead.
 
3129
                         */
 
3130
                        dbgprintf("HOSTNAME contains invalid characters, assuming it to be a TAG.\n");
 
3131
                        moveHOSTNAMEtoTAG(pMsg);
 
3132
                        MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
 
3133
                }
 
3134
 
 
3135
                /* now parse TAG - that should be present in message from
 
3136
                 * all sources.
 
3137
                 * This code is somewhat not compliant with RFC 3164. As of 3164,
 
3138
                 * the TAG field is ended by any non-alphanumeric character. In
 
3139
                 * practice, however, the TAG often contains dashes and other things,
 
3140
                 * which would end the TAG. So it is not desirable. As such, we only
 
3141
                 * accept colon and SP to be terminators. Even there is a slight difference:
 
3142
                 * 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.
 
3145
                 */
 
3146
                /* The following code in general is quick & dirty - I need to get
 
3147
                 * it going for a test, rgerhards 2004-11-16 */
 
3148
                /* lol.. we tried to solve it, just to remind ourselfs that 32 octets
 
3149
                 * is the max size ;) we need to shuffle the code again... Just for 
 
3150
                 * the records: the code is currently clean, but we could optimize it! */
 
3151
                if(!bTAGCharDetected) {
 
3152
                        uchar *pszTAG;
 
3153
                        if((pStrB = rsCStrConstruct()) == NULL) 
 
3154
                                return 1;
 
3155
                        rsCStrSetAllocIncrement(pStrB, 33);
 
3156
                        pWork = pBuf;
 
3157
                        iCnt = 0;
 
3158
                        while(*p2parse && *p2parse != ':' && *p2parse != ' ' && iCnt < 32) {
 
3159
                                rsCStrAppendChar(pStrB, *p2parse++);
 
3160
                                ++iCnt;
 
3161
                        }
 
3162
                        if(*p2parse == ':') {
 
3163
                                ++p2parse; 
 
3164
                                rsCStrAppendChar(pStrB, ':');
 
3165
                        }
 
3166
                        rsCStrFinish(pStrB);
 
3167
 
 
3168
                        rsCStrConvSzStrAndDestruct(pStrB, &pszTAG, 1);
 
3169
                        if(pszTAG == NULL)
 
3170
                        {       /* rger, 2005-11-10: no TAG found - this implies that what
 
3171
                                 * we have considered to be the HOSTNAME is most probably the
 
3172
                                 * TAG. We consider it so probable, that we now adjust it
 
3173
                                 * that way. So we pick up the previously set hostname, assign
 
3174
                                 * it to tag and use the sender system (from IP stack) as
 
3175
                                 * the hostname. This situation is the standard case with
 
3176
                                 * stock BSD syslogd.
 
3177
                                 */
 
3178
                                dbgprintf("No TAG in message, assuming that HOSTNAME is missing.\n");
 
3179
                                moveHOSTNAMEtoTAG(pMsg);
 
3180
                                MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
 
3181
                        } else { /* we have a TAG, so we can happily set it ;) */
 
3182
                                MsgAssignTAG(pMsg, pszTAG);
 
3183
                        }
 
3184
                } else {
 
3185
                        /* we have no TAG, so we ... */
 
3186
                        /*DO NOTHING*/;
 
3187
                }
 
3188
        } else {
 
3189
                /* we enter this code area when the user has instructed rsyslog NOT
 
3190
                 * to parse HOSTNAME and TAG - rgerhards, 2006-03-13
 
3191
                 */
 
3192
                if(!(flags & INTERNAL_MSG))
 
3193
                {
 
3194
                        dbgprintf("HOSTNAME and TAG not parsed by user configuraton.\n");
 
3195
                        MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
 
3196
                }
 
3197
        }
 
3198
 
 
3199
        /* The rest is the actual MSG */
 
3200
        MsgSetMSG(pMsg, p2parse);
 
3201
 
 
3202
        return 0; /* all ok */
 
3203
}
 
3204
 
 
3205
 
 
3206
/*
 
3207
 * Log a message to the appropriate log files, users, etc. based on
 
3208
 * the priority.
 
3209
 * rgerhards 2004-11-08: actually, this also decodes all but the PRI part.
 
3210
 * rgerhards 2004-11-09: ... but only, if syslogd could properly be initialized
 
3211
 *                       if not, we use emergency logging to the console and in
 
3212
 *                       this case, no further decoding happens.
 
3213
 * changed to no longer receive a plain message but a msg object instead.
 
3214
 * rgerhards-2004-11-16: OK, we are now up to another change... This method
 
3215
 * actually needs to PARSE the message. How exactly this needs to happen depends on
 
3216
 * a number of things. Most importantly, it depends on the source. For example,
 
3217
 * locally received messages (SOURCE_UNIXAF) do NOT have a hostname in them. So
 
3218
 * we need to treat them differntly form network-received messages which have.
 
3219
 * Well, actually not all network-received message really have a hostname. We
 
3220
 * can just hope they do, but we can not be sure. So this method tries to find
 
3221
 * whatever can be found in the message and uses that... Obviously, there is some
 
3222
 * potential for misinterpretation, which we simply can not solve under the
 
3223
 * circumstances given.
 
3224
 */
 
3225
void logmsg(int pri, msg_t *pMsg, int flags)
 
3226
{
 
3227
        char *msg;
 
3228
        char PRItext[20];
 
3229
 
 
3230
        assert(pMsg != NULL);
 
3231
        assert(pMsg->pszUxTradMsg != NULL);
 
3232
        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);
 
3236
 
 
3237
        /* rger 2005-11-24 (happy thanksgiving!): we now need to check if we have
 
3238
         * a traditional syslog message or one formatted according to syslog-protocol.
 
3239
         * We need to apply different parsers depending on that. We use the
 
3240
         * -protocol VERSION field for the detection.
 
3241
         */
 
3242
        if(msg[0] == '1' && msg[1] == ' ') {
 
3243
                dbgprintf("Message has syslog-protocol format.\n");
 
3244
                setProtocolVersion(pMsg, 1);
 
3245
                if(parseRFCSyslogMsg(pMsg, flags) == 1)
 
3246
                        return;
 
3247
        } else { /* we have legacy syslog */
 
3248
                dbgprintf("Message has legacy syslog format.\n");
 
3249
                setProtocolVersion(pMsg, 0);
 
3250
                if(parseLegacySyslogMsg(pMsg, flags) == 1)
 
3251
                        return;
 
3252
        }
 
3253
 
 
3254
        /* ---------------------- 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
        
 
3292
        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()
 
3406
{
 
3407
        int saved_errno = errno;
 
3408
        struct sigaction sigAct;
 
3409
 
 
3410
        memset(&sigAct, 0, sizeof (sigAct));
 
3411
        sigemptyset(&sigAct.sa_mask);
 
3412
        sigAct.sa_handler = reapchild;
 
3413
        sigaction(SIGCHLD, &sigAct, NULL);  /* reset signal handler -ASP */
 
3414
 
 
3415
        while(waitpid(-1, NULL, WNOHANG) > 0);
 
3416
        errno = saved_errno;
 
3417
}
 
3418
 
 
3419
 
 
3420
/* helper to domark to flush the individual action links via llExecFunc
 
3421
 * rgerhards, 2007-08-02
 
3422
 */
 
3423
DEFFUNC_llExecFunc(domarkActions)
 
3424
{
 
3425
        action_t *pAction = (action_t*) pData;
 
3426
 
 
3427
        assert(pAction != NULL);
 
3428
 
 
3429
        if (pAction->f_prevcount && now >= REPEATTIME(pAction)) {
 
3430
                dbgprintf("flush %s: repeated %d times, %d sec.\n",
 
3431
                    modGetStateName(pAction->pMod), pAction->f_prevcount,
 
3432
                    repeatinterval[pAction->f_repeatcount]);
 
3433
                fprintlog(pAction);
 
3434
                BACKOFF(pAction);
 
3435
        }
 
3436
 
 
3437
        return RS_RET_OK; /* we ignore errors, we can not do anything either way */
 
3438
}
 
3439
 
 
3440
 
 
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
 
3454
 */
 
3455
static void domark(void)
 
3456
{
 
3457
        register selector_t *f;
 
3458
 
 
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
                }
 
3471
        }
 
3472
}
 
3473
 
 
3474
 
 
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
static void debug_switch()
 
3495
{
 
3496
        struct sigaction sigAct;
 
3497
 
 
3498
        dbgprintf("Switching debugging_on to %s\n", (debugging_on == 0) ? "true" : "false");
 
3499
        debugging_on = (debugging_on == 0) ? 1 : 0;
 
3500
        
 
3501
        memset(&sigAct, 0, sizeof (sigAct));
 
3502
        sigemptyset(&sigAct.sa_mask);
 
3503
        sigAct.sa_handler = debug_switch;
 
3504
        sigaction(SIGUSR1, &sigAct, NULL);
 
3505
}
 
3506
 
 
3507
 
 
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);
 
3551
        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
}
 
3558
 
 
3559
/* doDie() is a signal handler. If called, it sets the bFinished variable
 
3560
 * to indicate the program should terminate. However, it does not terminate
 
3561
 * it itself, because that causes issues with multi-threading. The actual
 
3562
 * termination is then done on the main thread. This solution might introduce
 
3563
 * a minimal delay, but it is much cleaner than the approach of doing everything
 
3564
 * inside the signal handler.
 
3565
 * rgerhards, 2005-10-26
 
3566
 */
 
3567
static void doDie(int sig)
 
3568
{
 
3569
        dbgprintf("DoDie called.\n");
 
3570
        bFinished = sig;
 
3571
}
 
3572
 
 
3573
 
 
3574
/* 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
 
3578
 * safe to call exit() here. Just make sure that die() itself is not called
 
3579
 * at inapropriate places. As a general rule of thumb, it is a bad idea to add
 
3580
 * any calls to die() in new code!
 
3581
 * rgerhards, 2005-10-24
 
3582
 */
 
3583
static void die(int sig)
 
3584
{
 
3585
        char buf[256];
 
3586
        int i;
 
3587
 
 
3588
        if (sig) {
 
3589
                dbgprintf(" exiting on signal %d\n", sig);
 
3590
                (void) snprintf(buf, sizeof(buf) / sizeof(char),
 
3591
                 " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
 
3592
                 "\" x-pid=\"%d\"]" " exiting on signal %d.",
 
3593
                 (int) myPid, sig);
 
3594
                errno = 0;
 
3595
                logmsgInternal(LOG_SYSLOG|LOG_INFO, buf, ADDDATE);
 
3596
        }
 
3597
        
 
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! */
 
3604
        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
 
 
3626
        /* rger 2005-02-22
 
3627
         * now clean up the in-memory structures. OK, the OS
 
3628
         * would also take care of that, but if we do it
 
3629
         * ourselfs, this makes finding memory leaks a lot
 
3630
         * easier.
 
3631
         */
 
3632
        tplDeleteAll();
 
3633
 
 
3634
        remove_pid(PidFile);
 
3635
        if(glblHadMemShortage)
 
3636
                dbgprintf("Had memory shortage at least once during the run.\n");
 
3637
 
 
3638
        /* de-init some modules */
 
3639
        modExitIminternal();
 
3640
 
 
3641
        unregCfSysLineHdlrs();
 
3642
 
 
3643
        /* TODO: this would also be the right place to de-init the builtin output modules. We
 
3644
         * do not currently do that, because the module interface does not allow for
 
3645
         * it. This will come some time later (it's essential with loadable modules).
 
3646
         * For the time being, this is a memory leak on exit, but as the process is
 
3647
         * terminated, we do not really bother about it.
 
3648
         * rgerhards, 2007-08-03
 
3649
         * I have added some code now, but all that mod init/de-init should be moved to
 
3650
         * init, so that modules are unloaded and reloaded on HUP to. Eventually it should go
 
3651
         * into freeSelectors() - but that needs to be seen. -- rgerhards, 2007-08-09
 
3652
         */
 
3653
        modUnloadAndDestructAll();
 
3654
 
 
3655
        /* clean up auxiliary data */
 
3656
        if(pModDir != NULL)
 
3657
                free(pModDir);
 
3658
 
 
3659
        dbgprintf("Clean shutdown completed, bye.\n");
 
3660
        exit(0); /* "good" exit, this is the terminator function for rsyslog [die()] */
 
3661
}
 
3662
 
 
3663
/*
 
3664
 * Signal handler to terminate the parent process.
 
3665
 * rgerhards, 2005-10-24: this is only called during forking of the
 
3666
 * detached syslogd. I consider this method to be safe.
 
3667
 */
 
3668
static void doexit()
 
3669
{
 
3670
        exit(0); /* "good" exit, only during child-creation */
 
3671
}
 
3672
 
 
3673
 
 
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
/* set the action resume interval
 
3981
 */
 
3982
static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
 
3983
{
 
3984
        return actionSetGlobalResumeInterval(iNewVal);
 
3985
}
 
3986
 
 
3987
 
 
3988
/* set the processes umask (upon configuration request)
 
3989
 */
 
3990
static rsRetVal setUmask(void __attribute__((unused)) *pVal, int iUmask)
 
3991
{
 
3992
        umask(iUmask);
 
3993
        dbgprintf("umask set to 0%3.3o.\n", iUmask);
 
3994
 
 
3995
        return RS_RET_OK;
 
3996
}
 
3997
 
 
3998
 
 
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
/* helper to freeSelectors(), used with llExecFunc() to flush 
 
4043
 * pending output.  -- rgerhards, 2007-08-02
 
4044
 */
 
4045
DEFFUNC_llExecFunc(freeSelectorsActions)
 
4046
{
 
4047
        action_t *pAction = (action_t*) pData;
 
4048
 
 
4049
        assert(pAction != NULL);
 
4050
 
 
4051
        /* flush any pending output */
 
4052
        if(pAction->f_prevcount) {
 
4053
                fprintlog(pAction);
 
4054
        }
 
4055
 
 
4056
        return RS_RET_OK; /* never fails ;) */
 
4057
}
 
4058
 
 
4059
 
 
4060
/*  Close all open log files and free selector descriptor array.
 
4061
 */
 
4062
static void freeSelectors(void)
 
4063
{
 
4064
        selector_t *f;
 
4065
        selector_t *fPrev;
 
4066
 
 
4067
        if(Files != NULL) {
 
4068
                dbgprintf("Freeing log structures.\n");
 
4069
 
 
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
                for(f = Files ; f != NULL ; f = f->f_next) {
 
4080
                        llExecFunc(&f->llActList, freeSelectorsActions, NULL);
 
4081
                }
 
4082
 
 
4083
#               ifdef USE_PTHREADS
 
4084
                stopWorker();
 
4085
#               endif
 
4086
 
 
4087
                f = Files;
 
4088
                while (f != NULL) {
 
4089
                        fPrev = f;
 
4090
                        f = f->f_next;
 
4091
                        selectorDestruct(fPrev);
 
4092
                }
 
4093
 
 
4094
                /* Reflect the deletion of the selectors linked list. */
 
4095
                Files = NULL;
 
4096
                Initialized = 0;
 
4097
        }
 
4098
}
 
4099
 
 
4100
 
 
4101
/* helper to dbPrintInitInfo, to print out all actions via
 
4102
 * the llExecFunc() facility.
 
4103
 * rgerhards, 2007-08-02
 
4104
 */
 
4105
DEFFUNC_llExecFunc(dbgPrintInitInfoAction)
 
4106
{
 
4107
        DEFiRet;
 
4108
        iRet = actionDbgPrint((action_t*) pData);
 
4109
        printf("\n");
 
4110
 
 
4111
        return iRet;
 
4112
}
 
4113
 
 
4114
/* print debug information as part of init(). This pretty much
 
4115
 * outputs the whole config of rsyslogd. I've moved this code
 
4116
 * out of init() to clean it somewhat up.
 
4117
 * rgerhards, 2007-07-31
 
4118
 */
 
4119
static void dbgPrintInitInfo(void)
 
4120
{
 
4121
        register selector_t *f;
 
4122
        int iSelNbr = 1;
 
4123
        int i;
 
4124
 
 
4125
        printf("\nActive selectors:\n");
 
4126
        for (f = Files; f != NULL ; f = f->f_next) {
 
4127
                printf("Selector %d:\n", iSelNbr++);
 
4128
                if(f->pCSProgNameComp != NULL)
 
4129
                        printf("tag: '%s'\n", rsCStrGetSzStrNoNULL(f->pCSProgNameComp));
 
4130
                if(f->eHostnameCmpMode != HN_NO_COMP)
 
4131
                        printf("hostname: %s '%s'\n",
 
4132
                                f->eHostnameCmpMode == HN_COMP_MATCH ?
 
4133
                                        "only" : "allbut",
 
4134
                                rsCStrGetSzStrNoNULL(f->pCSHostnameComp));
 
4135
                if(f->f_filter_type == FILTER_PRI) {
 
4136
                        for (i = 0; i <= LOG_NFACILITIES; i++)
 
4137
                                if (f->f_filterData.f_pmask[i] == TABLE_NOPRI)
 
4138
                                        printf(" X ");
 
4139
                                else
 
4140
                                        printf("%2X ", f->f_filterData.f_pmask[i]);
 
4141
                } else {
 
4142
                        printf("PROPERTY-BASED Filter:\n");
 
4143
                        printf("\tProperty.: '%s'\n",
 
4144
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName));
 
4145
                        printf("\tOperation: ");
 
4146
                        if(f->f_filterData.prop.isNegated)
 
4147
                                printf("NOT ");
 
4148
                        printf("'%s'\n", getFIOPName(f->f_filterData.prop.operation));
 
4149
                        printf("\tValue....: '%s'\n",
 
4150
                               rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue));
 
4151
                        printf("\tAction...: ");
 
4152
                }
 
4153
 
 
4154
                printf("\nActions:\n");
 
4155
                llExecFunc(&f->llActList, dbgPrintInitInfoAction, NULL); /* actions */
 
4156
 
 
4157
                printf("\n");
 
4158
        }
 
4159
        printf("\n");
 
4160
        if(bDebugPrintTemplateList)
 
4161
                tplPrintList();
 
4162
        if(bDebugPrintModuleList)
 
4163
                modPrintList();
 
4164
        ochPrintList();
 
4165
 
 
4166
        if(bDebugPrintCfSysLineHandlerList)
 
4167
                dbgPrintCfSysLineHandlers();
 
4168
 
 
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",
 
4177
                bDropMalPTRMsgs ? "" : "not ");
 
4178
 
 
4179
        printf("Control characters are %sreplaced upon reception.\n",
 
4180
                        bEscapeCCOnRcv? "" : "not ");
 
4181
 
 
4182
        if(bEscapeCCOnRcv)
 
4183
                printf("Control character escape sequence prefix is '%c'.\n",
 
4184
                        cCCEscapeChar);
 
4185
 
 
4186
#ifdef  USE_PTHREADS
 
4187
        printf("Main queue size %d messages.\n", iMainMsgQueueSize);
 
4188
#endif
 
4189
}
 
4190
 
 
4191
 
 
4192
/* process a configuration file
 
4193
 * started with code from init() by rgerhards on 2007-07-31
 
4194
 */
 
4195
static rsRetVal processConfFile(uchar *pConfFile)
 
4196
{
 
4197
        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;
 
4288
}
 
4289
 
 
4290
 
 
4291
/* INIT -- Initialize syslogd from configuration table
 
4292
 * init() is called at initial startup AND each time syslogd is HUPed
 
4293
 */
 
4294
static void init(void)
 
4295
{
 
4296
        DEFiRet;
 
4297
        register int i;
 
4298
#ifdef CONT_LINE
 
4299
        char cbuf[BUFSIZ];
 
4300
#else
 
4301
        char cline[BUFSIZ];
 
4302
#endif
 
4303
        char bufStartUpMsg[512];
 
4304
        struct servent *sp;
 
4305
        struct sigaction sigAct;
 
4306
 
 
4307
        /* initialize some static variables */
 
4308
        pDfltHostnameCmp = NULL;
 
4309
        pDfltProgNameCmp = NULL;
 
4310
        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
 
 
4360
        dbgprintf("rsyslog %s.\n", VERSION);
 
4361
        dbgprintf("Called init.\n");
 
4362
 
 
4363
        /*  Close all open log files and free log descriptor array. */
 
4364
        freeSelectors();
 
4365
 
 
4366
        /* Unload all non-static modules */
 
4367
        dbgprintf("Unloading non-static modules.\n");
 
4368
        modUnloadAndDestructDynamic();
 
4369
 
 
4370
        dbgprintf("Clearing templates.\n");
 
4371
        tplDeleteNew();
 
4372
 
 
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
        /* re-setting values to defaults (where applicable) */
 
4382
        /* TODO: once we have loadable modules, we must re-visit this code. The reason is
 
4383
         * that config variables are not re-set, because the module is not yet loaded. On
 
4384
         * the other hand, that doesn't matter, because the module got unloaded and is then
 
4385
         * re-loaded, so the variables should be re-set via that way. In any case, we should
 
4386
         * think about the whole situation when we implement loadable plugins.
 
4387
         * rgerhards, 2007-07-31
 
4388
         */
 
4389
        cfsysline((uchar*)"ResetConfigVariables");
 
4390
 
 
4391
        /* open the configuration file */
 
4392
        if((iRet = processConfFile(ConfFile)) != RS_RET_OK) {
 
4393
                /* rgerhards: this code is executed to set defaults when the
 
4394
                 * config file could not be opened. We might think about
 
4395
                 * abandoning the run in this case - but this, too, is not
 
4396
                 * very clever... So we stick with what we have.
 
4397
                 * We ignore any errors while doing this - we would be lost anyhow...
 
4398
                 */
 
4399
                selector_t *f = NULL;
 
4400
                char szTTYNameBuf[TTY_NAME_MAX+1]; /* +1 for NULL character */
 
4401
                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);
 
4404
                if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
 
4405
                        snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
 
4406
                        cfline((uchar*)cbuf, &f);
 
4407
                }
 
4408
                selectorAddList(f);
 
4409
        }
 
4410
 
 
4411
        /* we are now done with reading the configuration. This is the right time to
 
4412
         * free some objects that were just needed for loading it. rgerhards 2005-10-19
 
4413
         */
 
4414
        if(pDfltHostnameCmp != NULL) {
 
4415
                rsCStrDestruct(pDfltHostnameCmp);
 
4416
                pDfltHostnameCmp = NULL;
 
4417
        }
 
4418
 
 
4419
        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
 
4469
        /* 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;
 
4480
 
 
4481
        if(Debug) {
 
4482
                dbgPrintInitInfo();
 
4483
        }
 
4484
 
 
4485
        /* we now generate the startup message. It now includes everything to
 
4486
         * identify this instance. -- rgerhards, 2005-08-17
 
4487
         */
 
4488
        snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char), 
 
4489
                 " [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
                );
 
4501
        logmsgInternal(LOG_SYSLOG|LOG_INFO, bufStartUpMsg, ADDDATE);
 
4502
 
 
4503
        memset(&sigAct, 0, sizeof (sigAct));
 
4504
        sigemptyset(&sigAct.sa_mask);
 
4505
        sigAct.sa_handler = sighup_handler;
 
4506
        sigaction(SIGHUP, &sigAct, NULL);
 
4507
 
 
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;
 
5185
}
 
5186
 
 
5187
 
 
5188
/* add a completely-processed selector (after config line parsing) to
 
5189
 * the linked list of selectors. We now need to check
 
5190
 * if it has any actions associated and, if so, link it to the linked
 
5191
 * list. If it has nothing associated with it, we can simply discard
 
5192
 * it.
 
5193
 * We have one special case during initialization: then, the current
 
5194
 * selector is NULL, which means we do not need to care about it at
 
5195
 * all.  -- rgerhards, 2007-08-01
 
5196
 */
 
5197
static rsRetVal selectorAddList(selector_t *f)
 
5198
{
 
5199
        DEFiRet;
 
5200
        int iActionCnt;
 
5201
 
 
5202
        static selector_t *nextp = NULL; /* TODO: make this go away (see comment below) */
 
5203
 
 
5204
        if(f != NULL) {
 
5205
                CHKiRet(llGetNumElts(&f->llActList, &iActionCnt));
 
5206
                if(iActionCnt == 0) {
 
5207
                        logerror("warning: selector line without actions will be discarded");
 
5208
                        selectorDestruct(f);
 
5209
                } 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
                        /* successfully created an entry */
 
5216
                        dbgprintf("selector line successfully processed\n");
 
5217
                        /* TODO: we should use the linked list class for the selector list, else we need to add globals
 
5218
                         * ... well nextp could be added temporarily...
 
5219
                         * Thanks to varmojfekoj for having the idea to just use "Files" to make this
 
5220
                         * code work. I had actually forgotten to fix the code here before moving to 1.18.0.
 
5221
                         * And, of course, I also did not migrate the selector_t structure to the linked list class.
 
5222
                         * However, that should still be one of the very next things to happen.
 
5223
                         * rgerhards, 2007-08-06
 
5224
                         */
 
5225
                        if(Files == NULL) {
 
5226
                                Files = f;
 
5227
                        } else {
 
5228
                                nextp->f_next = f;
 
5229
                        }
 
5230
                        nextp = f;
 
5231
                }
 
5232
        }
 
5233
 
 
5234
finalize_it:
 
5235
        return iRet;
 
5236
}
 
5237
 
 
5238
 
 
5239
/* Process a configuration file line in traditional "filter selector" format
 
5240
 */
 
5241
static rsRetVal cflineClassic(uchar *p, selector_t **pfCurr)
 
5242
{
 
5243
        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 */
 
5257
        } 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;
 
5377
}
 
5378
 
 
5379
 
 
5380
/*
 
5381
 * The following function is resposible for handling a SIGHUP signal.  Since
 
5382
 * we are now doing mallocs/free as part of init we had better not being
 
5383
 * doing this during a signal handler.  Instead this function simply sets
 
5384
 * a flag variable which will tell the main loop to go through a restart.
 
5385
 */
 
5386
void sighup_handler()
 
5387
{
 
5388
        struct sigaction sigAct;
 
5389
        
 
5390
        restart = 1;
 
5391
 
 
5392
        memset(&sigAct, 0, sizeof (sigAct));
 
5393
        sigemptyset(&sigAct.sa_mask);
 
5394
        sigAct.sa_handler = sighup_handler;
 
5395
        sigaction(SIGHUP, &sigAct, NULL);
 
5396
 
 
5397
        return;
 
5398
}
 
5399
 
 
5400
 
 
5401
/**
 
5402
 * getSubString
 
5403
 *
 
5404
 * Copy a string byte by byte until the occurrence  
 
5405
 * of a given separator.
 
5406
 *
 
5407
 * \param ppSrc         Pointer to a pointer of the source array of characters. If a
 
5408
                        separator detected the Pointer points to the next char after the
 
5409
                        separator. Except if the end of the string is dedected ('\n'). 
 
5410
                        Then it points to the terminator char. 
 
5411
 * \param pDst          Pointer to the destination array of characters. Here the substing
 
5412
                        will be stored.
 
5413
 * \param DstSize       Maximum numbers of characters to store.
 
5414
 * \param cSep          Separator char.
 
5415
 * \ret int             Returns 0 if no error occured.
 
5416
 */
 
5417
int getSubString(uchar **ppSrc,  char *pDst, size_t DstSize, char cSep)
 
5418
{
 
5419
        uchar *pSrc = *ppSrc;
 
5420
        int iErr = 0; /* 0 = no error, >0 = error */
 
5421
        while(*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
 
5422
                *pDst++ = *(pSrc)++;
 
5423
                DstSize--;
 
5424
        }
 
5425
        /* check if the Dst buffer was to small */
 
5426
        if (*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0')
 
5427
        { 
 
5428
                dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
 
5429
                iErr = 1;
 
5430
        }       
 
5431
        if (*pSrc == '\0' || *pSrc == '\n')
 
5432
                /* this line was missing, causing ppSrc to be invalid when it
 
5433
                 * was returned in case of end-of-string. rgerhards 2005-07-29
 
5434
                 */
 
5435
                *ppSrc = pSrc;
 
5436
        else
 
5437
                *ppSrc = pSrc+1;
 
5438
        *pDst = '\0';
 
5439
        return iErr;
 
5440
}
 
5441
 
 
5442
 
 
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
/* this function pulls all internal messages from the buffer
 
5486
 * and puts them into the processing engine.
 
5487
 * We can only do limited error handling, as this would not
 
5488
 * really help us. TODO: add error messages?
 
5489
 * rgerhards, 2007-08-03
 
5490
 */
 
5491
static void processImInternal(void)
 
5492
{
 
5493
        int iPri;
 
5494
        int iFlags;
 
5495
        msg_t *pMsg;
 
5496
 
 
5497
        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;
 
5743
}
 
5744
 
 
5745
 
 
5746
/* This is the main processing loop. It is called after successful initialization.
 
5747
 * When it returns, the syslogd terminates.
 
5748
 */
 
5749
static void mainloop(void)
 
5750
{
 
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
        struct timeval tvSelectTimeout;
 
5764
#endif
 
5765
#endif
 
5766
 
 
5767
        while(!bFinished){
 
5768
                errno  = 0;
 
5769
                maxfds = 0;
 
5770
                FD_ZERO (&readfds);
 
5771
 
 
5772
                /* first check if we have any internal messages queued and spit them out */
 
5773
                processImInternal();
 
5774
 
 
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;
 
5881
                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
                }
 
5901
                if(restart) {
 
5902
                        dbgprintf("\nReceived SIGHUP, reloading rsyslogd.\n");
 
5903
                        /* worker thread is stopped as part of init() */
 
5904
                        init();
 
5905
                        restart = 0;
 
5906
                        continue;
 
5907
                }
 
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
        }
 
5918
}
 
5919
 
 
5920
/* If user is not root, prints warnings or even exits 
 
5921
 * TODO: check all dynafiles for write permission
 
5922
 * ... but it is probably better to wait here until we have
 
5923
 * a module interface - rgerhards, 2007-07-23
 
5924
 */
 
5925
static void checkPermissions()
 
5926
{
 
5927
        /* we are not root */
 
5928
        if (geteuid() != 0)
 
5929
        {
 
5930
                fputs("WARNING: Local messages will not be logged! If you want to log them, run rsyslog as root.\n",stderr); 
 
5931
#ifdef SYSLOG_INET      
 
5932
                /* udp enabled and port number less than or equal to 1024 */
 
5933
                if ( AcceptRemote && (atoi(LogPort) <= 1024) )
 
5934
                        fprintf(stderr, "WARNING: Will not listen on UDP port %s. Use port number higher than 1024 or run rsyslog as root!\n", LogPort);
 
5935
                
 
5936
                /* tcp enabled and port number less or equal to 1024 */
 
5937
                if( bEnableTCP   && (atoi(TCPLstnPort) <= 1024) )
 
5938
                        fprintf(stderr, "WARNING: Will not listen on TCP port %s. Use port number higher than 1024 or run rsyslog as root!\n", TCPLstnPort);
 
5939
 
 
5940
                /* Neither explicit high UDP port nor explicit high TCP port.
 
5941
                 * It is useless to run anymore */
 
5942
                if( !(AcceptRemote && (atoi(LogPort) > 1024)) && !( bEnableTCP && (atoi(TCPLstnPort) > 1024)) )
 
5943
                {
 
5944
#endif
 
5945
                        fprintf(stderr, "ERROR: Nothing to log, no reason to run. Please run rsyslog as root.\n");
 
5946
                        exit(EXIT_FAILURE);
 
5947
#ifdef SYSLOG_INET
 
5948
                }
 
5949
#endif
 
5950
        }
 
5951
}
 
5952
 
 
5953
 
 
5954
/* load build-in modules
 
5955
 * very first version begun on 2007-07-23 by rgerhards
 
5956
 */
 
5957
static rsRetVal loadBuildInModules(void)
 
5958
{
 
5959
        DEFiRet;
 
5960
 
 
5961
        if((iRet = doModInit(modInitFile, (uchar*) "builtin-file", NULL)) != RS_RET_OK)
 
5962
                return iRet;
 
5963
#ifdef SYSLOG_INET
 
5964
        if((iRet = doModInit(modInitFwd, (uchar*) "builtin-fwd", NULL)) != RS_RET_OK)
 
5965
                return iRet;
 
5966
#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;
 
5971
 
 
5972
        /* dirty, but this must be for the time being: the usrmsg module must always be
 
5973
         * loaded as last module. This is because it processes any time of action selector.
 
5974
         * If we load it before other modules, these others will never have a chance of
 
5975
         * working with the config file. We may change that implementation so that a user name
 
5976
         * must start with an alnum, that would definitely help (but would it break backwards
 
5977
         * compatibility?). * rgerhards, 2007-07-23
 
5978
         * User names now must begin with:
 
5979
         *   [a-zA-Z0-9_.]
 
5980
         */
 
5981
        if((iRet = doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg", NULL)) != RS_RET_OK)
 
5982
                return iRet;
 
5983
 
 
5984
        /* ok, initialization of the command handler probably does not 100% belong right in
 
5985
         * this space here. However, with the current design, this is actually quite a good
 
5986
         * place to put it. We might decide to shuffle it around later, but for the time
 
5987
         * being, the code has found its home here. A not-just-sideeffect of this decision
 
5988
         * is that rsyslog will terminate if we can not register our built-in config commands.
 
5989
         * This, I think, is the right thing to do. -- rgerhards, 2007-07-31
 
5990
         */
 
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));
 
6009
        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));
 
6013
 
 
6014
finalize_it:
 
6015
        return iRet;
 
6016
}
 
6017
 
 
6018
 
 
6019
/* print version and compile-time setting information.
 
6020
 */
 
6021
static void printVersion(void)
 
6022
{
 
6023
        printf("rsyslogd %s, ", VERSION);
 
6024
        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
#ifdef FEATURE_REGEXP
 
6031
        printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
 
6032
#else
 
6033
        printf("\tFEATURE_REGEXP:\t\t\t\tNo\n");
 
6034
#endif
 
6035
#ifndef NOLARGEFILE
 
6036
        printf("\tFEATURE_LARGEFILE:\t\t\tYes\n");
 
6037
#else
 
6038
        printf("\tFEATURE_LARGEFILE:\t\t\tNo\n");
 
6039
#endif
 
6040
#ifdef  USE_NETZIP
 
6041
        printf("\tFEATURE_NETZIP (message compression):\tYes\n");
 
6042
#else
 
6043
        printf("\tFEATURE_NETZIP (message compression):\tNo\n");
 
6044
#endif
 
6045
#ifdef  SYSLOG_INET
 
6046
        printf("\tSYSLOG_INET (Internet/remote support):\tYes\n");
 
6047
#else
 
6048
        printf("\tSYSLOG_INET (Internet/remote support):\tNo\n");
 
6049
#endif
 
6050
#ifndef NDEBUG
 
6051
        printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
 
6052
#else
 
6053
        printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
 
6054
#endif
 
6055
        printf("\nSee http://www.rsyslog.com for more information.\n");
 
6056
}
 
6057
 
 
6058
 
 
6059
/* This function is called after initial initalization. It is used to
 
6060
 * move code out of the too-long main() function.
 
6061
 * rgerhards, 2007-10-17
 
6062
 */
 
6063
static void mainThread()
 
6064
{
 
6065
        DEFiRet;
 
6066
        uchar *pTmp;
 
6067
 
 
6068
        /* doing some core initializations */
 
6069
        if((iRet = modInitIminternal()) != RS_RET_OK) {
 
6070
                fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
 
6071
                        iRet);
 
6072
                exit(1); /* "good" exit, leaving at init for fatal error */
 
6073
        }
 
6074
 
 
6075
        if((iRet = loadBuildInModules()) != RS_RET_OK) {
 
6076
                fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
 
6077
                        iRet);
 
6078
                exit(1); /* "good" exit, leaving at init for fatal error */
 
6079
        }
 
6080
 
 
6081
        /* Note: signals MUST be processed by the thread this code is running in. The reason
 
6082
         * is that we need to interrupt the select() system call. -- rgerhards, 2007-10-17
 
6083
         */
 
6084
 
 
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);
 
6091
        pTmp = template_WallFmt;
 
6092
        tplAddLine(" WallFmt", &pTmp);
 
6093
        pTmp = template_StdFwdFmt;
 
6094
        tplAddLine(" StdFwdFmt", &pTmp);
 
6095
        pTmp = template_StdUsrMsgFmt;
 
6096
        tplAddLine(" StdUsrMsgFmt", &pTmp);
 
6097
        pTmp = template_StdDBFmt;
 
6098
        tplLastStaticInit(tplAddLine(" StdDBFmt", &pTmp));
 
6099
 
 
6100
        dbgprintf("Starting.\n");
 
6101
        init();
 
6102
        if(Debug) {
 
6103
                dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n");
 
6104
                debugging_on = 1;
 
6105
        }
 
6106
        /* Send a signal to the parent so it can terminate.
 
6107
         */
 
6108
        if (myPid != ppid)
 
6109
                kill (ppid, SIGTERM);
 
6110
 
 
6111
        /* END OF INTIALIZATION
 
6112
         * ... but keep in mind that we might do a restart and thus init() might
 
6113
         * be called again. If that happens, we must shut down the worker thread,
 
6114
         * do the init() and then restart things.
 
6115
         * rgerhards, 2005-10-24
 
6116
         */
 
6117
 
 
6118
        mainloop();
 
6119
 
 
6120
        /* do any de-init's that need to be done AFTER this comment */
 
6121
        die(bFinished);
 
6122
}
 
6123
 
 
6124
 
 
6125
/* This is the main entry point into rsyslogd. Over time, we should try to
 
6126
 * modularize it a bit more...
 
6127
 */
 
6128
int main(int argc, char **argv)
 
6129
{       
 
6130
        register int i;
 
6131
        register char *p;
 
6132
        int num_fds;
 
6133
        int ch;
 
6134
        struct hostent *hent;
 
6135
        extern int optind;
 
6136
        extern char *optarg;
 
6137
        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
 
6147
 
 
6148
        ppid = getpid();
 
6149
 
 
6150
        if(chdir ("/") != 0)
 
6151
                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
 
 
6157
        /* END core initializations */
 
6158
 
 
6159
        while ((ch = getopt(argc, argv, "46Aa:dehi:f:l:m:nop:r::s:t:u:vwx")) != EOF) {
 
6160
                switch((char)ch) {
 
6161
                case '4':
 
6162
                        family = PF_INET;
 
6163
                        break;
 
6164
                case '6':
 
6165
                        family = PF_INET6;
 
6166
                        break;
 
6167
                case 'A':
 
6168
                        send_to_all++;
 
6169
                        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);
 
6182
                        break;
 
6183
                case 'd':               /* debug */
 
6184
                        Debug = 1;
 
6185
                        break;
 
6186
                case 'e':               /* log every message (no repeat message supression) */
 
6187
                        logEveryMsg = 1;
 
6188
                        break;
 
6189
                case 'f':               /* configuration file */
 
6190
                        ConfFile = (uchar*) optarg;
 
6191
                        break;
 
6192
                case 'h':
 
6193
                        NoHops = 0;
 
6194
                        break;
 
6195
                case 'i':               /* pid file name */
 
6196
                        PidFile = optarg;
 
6197
                        break;
 
6198
                case 'l':
 
6199
                        if (LocalHosts) {
 
6200
                                fprintf (stderr, "rsyslogd: Only one -l argument allowed," \
 
6201
                                        "the first one is taken.\n");
 
6202
                        } else {
 
6203
                                LocalHosts = crunch_list(optarg);
 
6204
                        }
 
6205
                        break;
 
6206
                case 'm':               /* mark interval */
 
6207
                        MarkInterval = atoi(optarg) * 60;
 
6208
                        break;
 
6209
                case 'n':               /* don't fork */
 
6210
                        NoFork = 1;
 
6211
                        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;
 
6218
                case 'r':               /* accept remote messages */
 
6219
#ifdef SYSLOG_INET
 
6220
                        AcceptRemote = 1;
 
6221
                        if(optarg == NULL)
 
6222
                                LogPort = "0";
 
6223
                        else
 
6224
                                LogPort = optarg;
 
6225
#else
 
6226
                        fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support");
 
6227
#endif
 
6228
                        break;
 
6229
                case 's':
 
6230
                        if (StripDomains) {
 
6231
                                fprintf (stderr, "rsyslogd: Only one -s argument allowed," \
 
6232
                                        "the first one is taken.\n");
 
6233
                        } else {
 
6234
                                StripDomains = crunch_list(optarg);
 
6235
                        }
 
6236
                        break;
 
6237
                case 't':               /* enable tcp logging */
 
6238
#ifdef SYSLOG_INET
 
6239
                        configureTCPListen(optarg);
 
6240
#else
 
6241
                        fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support");
 
6242
#endif
 
6243
                        break;
 
6244
                case 'u':               /* misc user settings */
 
6245
                        if(atoi(optarg) == 1)
 
6246
                                bParseHOSTNAMEandTAG = 0;
 
6247
                        break;
 
6248
                case 'v':
 
6249
                        printVersion();
 
6250
                        exit(0); /* exit for -v option - so this is a "good one" */
 
6251
                case 'w':               /* disable disallowed host warnigs */
 
6252
                        option_DisallowWarning = 0;
 
6253
                        break;
 
6254
                case 'x':               /* disable dns for remote messages */
 
6255
                        DisableDNS = 1;
 
6256
                        break;
 
6257
                case '?':              
 
6258
                default:
 
6259
                        usage();
 
6260
                }
 
6261
        }
 
6262
 
 
6263
        if ((argc -= optind))
 
6264
                usage();
 
6265
 
 
6266
        checkPermissions();
 
6267
 
 
6268
        if ( !(Debug || NoFork) )
 
6269
        {
 
6270
                dbgprintf("Checking pidfile.\n");
 
6271
                if (!check_pid(PidFile))
 
6272
                {
 
6273
                        memset(&sigAct, 0, sizeof (sigAct));
 
6274
                        sigemptyset(&sigAct.sa_mask);
 
6275
                        sigAct.sa_handler = doexit;
 
6276
                        sigaction(SIGTERM, &sigAct, NULL);
 
6277
 
 
6278
                        if (fork()) {
 
6279
                                /*
 
6280
                                 * Parent process
 
6281
                                 */
 
6282
                                sleep(300);
 
6283
                                /*
 
6284
                                 * Not reached unless something major went wrong.  5
 
6285
                                 * minutes should be a fair amount of time to wait.
 
6286
                                 * Please note that this procedure is important since
 
6287
                                 * the father must not exit before syslogd isn't
 
6288
                                 * initialized or the klogd won't be able to flush its
 
6289
                                 * logs.  -Joey
 
6290
                                 */
 
6291
                                exit(1); /* "good" exit - after forking, not diasabling anything */
 
6292
                        }
 
6293
                        num_fds = getdtablesize();
 
6294
                        for (i= 0; i < num_fds; i++)
 
6295
                                (void) close(i);
 
6296
                        untty();
 
6297
                }
 
6298
                else
 
6299
                {
 
6300
                        fputs(" Already running.\n", stderr);
 
6301
                        exit(1); /* "good" exit, done if syslogd is already running */
 
6302
                }
 
6303
        }
 
6304
        else
 
6305
                debugging_on = 1;
 
6306
 
 
6307
        /* tuck my process id away */
 
6308
        if ( !Debug )
 
6309
        {
 
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);
 
6322
                        exit(1); /* exit during startup - questionable */
 
6323
                }
 
6324
        } /* if ( !Debug ) */
 
6325
        myPid = getpid();       /* save our pid for further testing (also used for messages) */
 
6326
 
 
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
        memset(&sigAct, 0, sizeof (sigAct));
 
6369
        sigemptyset(&sigAct.sa_mask);
 
6370
 
 
6371
        sigAct.sa_handler = doDie;
 
6372
        sigaction(SIGTERM, &sigAct, NULL);
 
6373
        sigAct.sa_handler = Debug ? doDie : SIG_IGN;
 
6374
        sigaction(SIGINT, &sigAct, NULL);
 
6375
        sigaction(SIGQUIT, &sigAct, NULL);
 
6376
        sigAct.sa_handler = reapchild;
 
6377
        sigaction(SIGCHLD, &sigAct, NULL);
 
6378
        sigAct.sa_handler = domarkAlarmHdlr;
 
6379
        sigaction(SIGALRM, &sigAct, NULL);
 
6380
        sigAct.sa_handler = Debug ? debug_switch : SIG_IGN;
 
6381
        sigaction(SIGUSR1, &sigAct, NULL);
 
6382
        sigAct.sa_handler = SIG_IGN;
 
6383
        sigaction(SIGPIPE, &sigAct, NULL);
 
6384
        sigaction(SIGXFSZ, &sigAct, NULL); /* do not abort if 2gig file limit is hit */
 
6385
        (void) alarm(TIMERINTVL);
 
6386
 
 
6387
        mainThread();
 
6388
 
 
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);
 
6399
 
 
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);
 
6406
        
 
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
 
 
6413
        return 0;
 
6414
}
 
6415
 
 
6416
 
 
6417
/* vi:set ai:
 
6418
 */