/**
* \brief This is the main file of the rsyslogd daemon.
*
* Please visit the rsyslog project at
*
* http://www.rsyslog.com
*
* to learn more about it and discuss any questions you may have.
*
* Please note that as of now, a lot of the code in this file stems
* from the sysklogd project. To learn more over this project, please
* visit
*
* http://www.infodrom.org/projects/sysklogd/
*
* I would like to express my thanks to the developers of the sysklogd
* package - without it, I would have had a much harder start...
*
* Please note that I made quite some changes to the orignal package.
* I expect to do even more changes - up
* to a full rewrite - to meet my design goals, which among others
* contain a (at least) dual-thread design with a memory buffer for
* storing received bursts of data. This is also the reason why I
* kind of "forked" a completely new branch of the package. My intension
* is to do many changes and only this initial release will look
* similar to sysklogd (well, one never knows...).
*
* As I have made a lot of modifications, please assume that all bugs
* in this package are mine and not those of the sysklogd team.
*
* As of this writing, there already exist heavy
* modifications to the orginal sysklogd package. I suggest to no
* longer rely too much on code knowledge you eventually have with
* sysklogd - rgerhards 2005-07-05
* The code is now almost completely different. Be careful!
* rgerhards, 2006-11-30
*
* I have decided to put my code under the GPL. The sysklog package
* is distributed under the BSD license. As such, this package here
* currently comes with two licenses. Both are given below. As it is
* probably hard for you to see what was part of the sysklogd package
* and what is part of my code, I suggest that you visit the
* sysklogd site on the URL above if you would like to base your
* development on a version that is not under the GPL.
*
* This Project was intiated and is maintained by
* Rainer Gerhards <rgerhards@hq.adiscon.com>. See
* AUTHORS to learn who helped make it become a reality.
*
* If you have questions about rsyslogd in general, please email
* info@adiscon.com. To learn more about rsyslogd, please visit
* http://www.rsyslog.com.
*
* \author Rainer Gerhards <rgerhards@adiscon.com>
* \date 2003-10-17
* Some initial modifications on the sysklogd package to support
* liblogging. These have actually not yet been merged to the
* source you see currently (but they hopefully will)
*
* \date 2004-10-28
* Restarted the modifications of sysklogd. This time, we
* focus on a simpler approach first. The initial goal is to
* provide MySQL database support (so that syslogd can log
* to the database).
*
* rsyslog - An Enhanced syslogd Replacement.
* Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
#include "config.h"
#include "rsyslog.h"
#ifdef __FreeBSD__
#define BSD
#endif
/* change the following setting to e.g. 32768 if you would like to
* support large message sizes for IHE (32k is the current maximum
* needed for IHE). I was initially tempted to increase it to 32k,
* but there is a large memory footprint with the current
* implementation in rsyslog. This will change as the processing
* changes, but I have re-set it to 1k, because the vast majority
* of messages is below that and the memory savings is huge, at
* least compared to the overall memory footprint.
*
* If you intend to receive Windows Event Log data (e.g. via
* EventReporter - www.eventreporter.com), you might want to
* increase this number to an even higher value, as event
* log messages can be very lengthy.
* rgerhards, 2005-07-05
*
* during my recent testing, it showed that 4k seems to be
* the typical maximum for UDP based syslog. This is a IP stack
* restriction. Not always ... but very often. If you go beyond
* that value, be sure to test that rsyslogd actually does what
* you think it should do ;) Also, it is a good idea to check the
* doc set for anything on IHE - it most probably has information on
* message sizes.
* rgerhards, 2005-08-05
*
* I have increased the default message size to 2048 to be in sync
* with recent IETF syslog standardization efforts.
* rgerhards, 2006-11-30
*
* I have removed syslogdPanic(). That function was supposed to be used
* for logging in low-memory conditons. Ever since it was introduced, it
* was a wrapper for dbgprintf(). A more intelligent choice was hard to
* find. After all, if we are short on memory, doing anything fance will
* again cause memory problems. I have now modified the code so that
* those elements for which we do not get memory are simply discarded.
* That might be a single property like the TAG, but it might also be
* a complete message. The overall goal of this code change is to keep
* rsyslogd up and running, while we sacrifice some messages to reach
* that goal. It also keeps the code cleaner. A real out of memory
* condition is highly unlikely. If it happens, there will probably be
* much more trouble on the system in question. Anyhow - rsyslogd will
* most probably be able to survive it and carry on with processing
* once the situation has been resolved.
*/
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define CONT_LINE 1 /* Allow continuation lines */
#ifdef MTRACE
#include <mcheck.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <ctype.h>
#define GNU_SOURCE
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <dlfcn.h>
#include <sys/syslog.h>
#include <sys/param.h>
#ifdef __sun
#include <errno.h>
#else
#include <sys/errno.h>
#endif
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/un.h>
#include <sys/time.h>
#ifdef BSD
# include <sys/timespec.h>
#endif
#include <sys/resource.h>
#include <signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fnmatch.h>
#include <dirent.h>
#ifndef __sun
#endif
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "pidfile.h"
#include <assert.h>
#ifdef USE_PTHREADS
#include <pthread.h>
#endif
#if HAVE_PATHS_H
#include <paths.h>
#endif
/* handle some defines missing on more than one platform */
#ifndef SUN_LEN
#define SUN_LEN(su) \
(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif
#include "srUtils.h"
#include "stringbuf.h"
#include "syslogd-types.h"
#include "template.h"
#include "outchannel.h"
#include "syslogd.h"
#include "net.h" /* struct NetAddr */
#include "parse.h"
#include "msg.h"
#include "modules.h"
#include "action.h"
#include "tcpsyslog.h"
#include "iminternal.h"
#include "cfsysline.h"
#include "omshell.h"
#include "omusrmsg.h"
#include "omfwd.h"
#include "omfile.h"
#include "omdiscard.h"
/* We define our own set of syslog defintions so that we
* do not need to rely on (possibly different) implementations.
* 2007-07-19 rgerhards
*/
/* missing definitions for solaris
* 2006-02-16 Rger
*/
#ifdef __sun
# define LOG_AUTHPRIV LOG_AUTH
#endif
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
#define LOG_FTP (11<<3) /* ftp daemon */
#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
#ifndef UTMP_FILE
#ifdef UTMP_FILENAME
#define UTMP_FILE UTMP_FILENAME
#else
#ifdef _PATH_UTMP
#define UTMP_FILE _PATH_UTMP
#else
#define UTMP_FILE "/etc/utmp"
#endif
#endif
#endif
#ifndef _PATH_LOGCONF
#define _PATH_LOGCONF "/etc/rsyslog.conf"
#endif
#ifndef _PATH_MODDIR
#define _PATH_MODDIR "/lib/rsyslog/"
#endif
#if defined(SYSLOGD_PIDNAME)
#undef _PATH_LOGPID
#if defined(FSSTND)
#ifdef BSD
#define _PATH_VARRUN "/var/run/"
#endif
#ifdef __sun
#define _PATH_VARRUN "/var/run/"
#endif
#define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
#else
#define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
#endif
#else
#ifndef _PATH_LOGPID
#if defined(FSSTND)
#define _PATH_LOGPID _PATH_VARRUN "rsyslogd.pid"
#else
#define _PATH_LOGPID "/etc/rsyslogd.pid"
#endif
#endif
#endif
#ifndef _PATH_DEV
#define _PATH_DEV "/dev/"
#endif
#ifndef _PATH_CONSOLE
#define _PATH_CONSOLE "/dev/console"
#endif
#ifndef _PATH_TTY
#define _PATH_TTY "/dev/tty"
#endif
#ifndef _PATH_LOG
#ifdef BSD
#define _PATH_LOG "/var/run/log"
#else
#define _PATH_LOG "/dev/log"
#endif
#endif
/* IPv6 compatibility layer for older platforms
* We need to handle a few things different if we are running
* on an older platform which does not support all the glory
* of IPv6. We try to limit toll on features and reliability,
* but obviously it is better to run rsyslog on a platform that
* supports everything...
* rgerhards, 2007-06-22
*/
#ifndef AI_NUMERICSERV
# define AI_NUMERICSERV 0
#endif
static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
static char *PidFile = _PATH_LOGPID; /* read-only after startup */
static uchar *pModDir = NULL; /* read-only after startup */
char ctty[] = _PATH_CONSOLE; /* this is read-only; used by omfile -- TODO: remove that dependency */
static pid_t myPid; /* our pid for use in self-generated messages, e.g. on startup */
/* mypid is read-only after the initial fork() */
static int debugging_on = 0; /* read-only, except on sig USR1 */
static int restart = 0; /* do restart (config read) - multithread safe */
static int bRequestDoMark = 0; /* do mark processing? (multithread safe) */
#define MAXFUNIX 20
int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */
int startIndexUxLocalSockets = 0; /* process funix from that index on (used to
* suppress local logging. rgerhards 2005-08-01
* read-only after startup
*/
int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */
char *funixn[MAXFUNIX] = { _PATH_LOG }; /* read-only after startup */
int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
#define TABLE_NOPRI 0 /* Value to indicate no priority in f_pmask */
#define TABLE_ALLPRI 0xFF /* Value to indicate all priorities in f_pmask */
#define LOG_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */
/* definitions used for doNameLine to differentiate between different command types
* (with otherwise identical code). This is a left-over from the previous config
* system. It stays, because it is still useful. So do not wonder why it looks
* somewhat strange (at least its name). -- rgerhards, 2007-08-01
*/
enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2};
/* The following global variables are used for building
* tag and host selector lines during startup and config reload.
* This is stored as a global variable pool because of its ease. It is
* also fairly compatible with multi-threading as the stratup code must
* be run in a single thread anyways. So there can be no race conditions. These
* variables are no longer used once the configuration has been loaded (except,
* of course, during a reload). rgerhards 2005-10-18
*/
static EHostnameCmpMode eDfltHostnameCmpMode;
static rsCStrObj *pDfltHostnameCmp;
static rsCStrObj *pDfltProgNameCmp;
/* supporting structures for multithreading */
#ifdef USE_PTHREADS
/* this is the first approach to a queue, this time with static
* memory.
*/
typedef struct {
void** pbuf;
long head, tail;
int full, empty;
pthread_mutex_t *mut;
pthread_cond_t *notFull, *notEmpty;
} msgQueue;
int iMainMsgQueueSize;
int bRunningMultithreaded = 0; /* Is this program running in multithreaded mode? */
msgQueue *pMsgQueue = NULL;
static pthread_t thrdWorker;
static int bGlblDone = 0;
#endif
/* END supporting structures for multithreading */
static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
* parsed inside message - rgerhards, 2006-03-13 */
static int bFinished = 0; /* used by termination signal handler, read-only except there
* is either 0 or the number of the signal that requested the
* termination.
*/
/*
* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
* we move to the next interval until we reach the largest.
*/
int repeatinterval[] = { 30, 60 }; /* # of secs before flush */
#define MAXREPEAT ((int)((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1))
#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
(f)->f_repeatcount = MAXREPEAT; \
}
#ifdef SYSLOG_INET
union sockunion {
struct sockinet {
u_char si_len;
u_char si_family;
} su_si;
struct sockaddr_in su_sin;
struct sockaddr_in6 su_sin6;
};
#endif
#define LIST_DELIMITER ':' /* delimiter between two hosts */
struct filed *Files = NULL; /* read-only after init() (but beware of sigusr1!) */
struct code {
char *c_name;
int c_val;
};
static struct code PriNames[] = {
{"alert", LOG_ALERT},
{"crit", LOG_CRIT},
{"debug", LOG_DEBUG},
{"emerg", LOG_EMERG},
{"err", LOG_ERR},
{"error", LOG_ERR}, /* DEPRECATED */
{"info", LOG_INFO},
{"none", INTERNAL_NOPRI}, /* INTERNAL */
{"notice", LOG_NOTICE},
{"panic", LOG_EMERG}, /* DEPRECATED */
{"warn", LOG_WARNING}, /* DEPRECATED */
{"warning", LOG_WARNING},
{"*", TABLE_ALLPRI},
{NULL, -1}
};
static struct code FacNames[] = {
{"auth", LOG_AUTH},
{"authpriv", LOG_AUTHPRIV},
{"cron", LOG_CRON},
{"daemon", LOG_DAEMON},
{"kern", LOG_KERN},
{"lpr", LOG_LPR},
{"mail", LOG_MAIL},
{"mark", LOG_MARK}, /* INTERNAL */
{"news", LOG_NEWS},
{"security", LOG_AUTH}, /* DEPRECATED */
{"syslog", LOG_SYSLOG},
{"user", LOG_USER},
{"uucp", LOG_UUCP},
#if defined(LOG_FTP)
{"ftp", LOG_FTP},
#endif
{"local0", LOG_LOCAL0},
{"local1", LOG_LOCAL1},
{"local2", LOG_LOCAL2},
{"local3", LOG_LOCAL3},
{"local4", LOG_LOCAL4},
{"local5", LOG_LOCAL5},
{"local6", LOG_LOCAL6},
{"local7", LOG_LOCAL7},
{NULL, -1},
};
static pid_t ppid; /* This is a quick and dirty hack used for spliting main/startup thread */
/* global variables for config file state */
static int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
int Debug; /* debug flag - read-only after startup */
static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
static uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
static int bEscapeCCOnRcv; /* escape control characters on reception: 0 - no, 1 - yes */
static int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
static int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
static int logEveryMsg = 0;/* no repeat message processing - read-only after startup
* 0 - suppress duplicate messages
* 1 - do NOT suppress duplicate messages
*/
/* end global config file state variables */
static unsigned int Forwarding = 0;
static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */
char *LocalDomain; /* our local domain name - read-only after startup */
int *finet = NULL; /* Internet datagram sockets, first element is nbr of elements
* read-only after init(), but beware of restart! */
static char *LogPort = "514"; /* port number for INET connections */
static int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both), set via cmdline */
int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
static int MarkSeq = 0; /* mark sequence number - modified in domark() only */
static int NoFork = 0; /* don't fork - don't run in daemon mode - read-only after startup */
static int AcceptRemote = 0;/* receive messages that come via UDP - read-only after startup */
int DisableDNS = 0; /* don't look up IP addresses of remote messages */
char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
int NoHops = 1; /* Can we bounce syslog messages through an
intermediate host. Read-only after startup */
static int Initialized = 0; /* set when we have initialized ourselves
* rgerhards 2004-11-09: and by initialized, we mean that
* the configuration file could be properly read AND the
* syslog/udp port could be obtained (the later is debatable).
* It is mainly a setting used for emergency logging: if
* something really goes wild, we can not do as indicated in
* the log file, but we still log messages to the system
* console. This is probably the best that can be done in
* such a case.
* read-only after startup, but modified during restart
*/
extern int errno;
/* This structure represents the files that will have log
* copies printed.
* RGerhards 2004-11-08: Each instance of the filed structure
* describes what I call an "output channel". This is important
* to mention as we now allow database connections to be
* present in the filed structure. If helps immensely, if we
* think of it as the abstraction of an output channel.
* rgerhards, 2005-10-26: The structure below provides ample
* opportunity for non-thread-safety. Each of the variable
* accesses must be carefully evaluated, many of them probably
* be guarded by mutexes. But beware of deadlocks...
* rgerhards, 2007-08-01: as you can see, the structure has shrunk pretty much. I will
* remove some of the comments some time. It's still the structure that controls much
* of the processing that goes on in syslogd, but it now has lots of helpers.
*/
struct filed {
struct filed *f_next; /* next in linked list */
/* filter properties */
enum {
FILTER_PRI = 0, /* traditional PRI based filer */
FILTER_PROP = 1 /* extended filter, property based */
} f_filter_type;
EHostnameCmpMode eHostnameCmpMode;
rsCStrObj *pCSHostnameComp; /* hostname to check */
rsCStrObj *pCSProgNameComp; /* tag to check or NULL, if not to be checked */
union {
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
struct {
rsCStrObj *pCSPropName;
enum {
FIOP_NOP = 0, /* do not use - No Operation */
FIOP_CONTAINS = 1, /* contains string? */
FIOP_ISEQUAL = 2, /* is (exactly) equal? */
FIOP_STARTSWITH = 3, /* starts with a string? */
FIOP_REGEX = 4 /* matches a regular expression? */
} operation;
rsCStrObj *pCSCompValue; /* value to "compare" against */
char isNegated; /* actually a boolean ;) */
} prop;
} f_filterData;
linkedList_t llActList; /* list of configured actions */
};
typedef struct filed selector_t; /* new type name */
/* support for simple textual representation of FIOP names
* rgerhards, 2005-09-27
*/
static char* getFIOPName(unsigned iFIOP)
{
char *pRet;
switch(iFIOP) {
case FIOP_CONTAINS:
pRet = "contains";
break;
case FIOP_ISEQUAL:
pRet = "isequal";
break;
case FIOP_STARTSWITH:
pRet = "startswith";
break;
case FIOP_REGEX:
pRet = "regex";
break;
default:
pRet = "NOP";
break;
}
return pRet;
}
/* Reset config variables to default values.
* rgerhards, 2007-07-17
*/
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
cCCEscapeChar = '#';
bActExecWhenPrevSusp = 0;
bDebugPrintTemplateList = 1;
bDebugPrintCfSysLineHandlerList = 1;
bDebugPrintModuleList = 1;
bEscapeCCOnRcv = 1; /* default is to escape control characters */
bReduceRepeatMsgs = (logEveryMsg == 1) ? 0 : 1;
bDropMalPTRMsgs = 0;
if(pModDir != NULL) {
free(pModDir);
pModDir = NULL;
}
#ifdef USE_PTHREADS
iMainMsgQueueSize = 10000;
#endif
#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
if (gss_listen_service_name != NULL) {
free(gss_listen_service_name);
gss_listen_service_name = NULL;
}
#endif
return RS_RET_OK;
}
/* support for defining allowed TCP and UDP senders. We use the same
* structure to implement this (a linked list), but we define two different
* list roots, one for UDP and one for TCP.
* rgerhards, 2005-09-26
*/
#ifdef SYSLOG_INET
/* All of the five below are read-only after startup */
static struct AllowedSenders *pAllowedSenders_UDP = NULL; /* the roots of the allowed sender */
struct AllowedSenders *pAllowedSenders_TCP = NULL; /* lists. If NULL, all senders are ok! */
static struct AllowedSenders *pLastAllowedSenders_UDP = NULL; /* and now the pointers to the last */
static struct AllowedSenders *pLastAllowedSenders_TCP = NULL; /* element in the respective list */
#endif /* #ifdef SYSLOG_INET */
int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
/* hardcoded standard templates (used for defaults) */
static uchar template_TraditionalFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
static uchar template_StdFwdFmt[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%\"";
static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
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";
/* end template */
/* up to the next comment, prototypes that should be removed by reordering */
#ifdef USE_PTHREADS
static msgQueue *queueInit (void);
static void *singleWorker(); /* REMOVEME later 2005-10-24 */
#endif
/* Function prototypes. */
static char **crunch_list(char *list);
static void printline(char *hname, char *msg, int iSource);
static void logmsg(int pri, msg_t*, int flags);
static rsRetVal fprintlog(action_t *pAction);
static void reapchild();
static void debug_switch();
static rsRetVal cfline(uchar *line, selector_t **pfCurr);
static int decode(uchar *name, struct code *codetab);
static void sighup_handler();
static void die(int sig);
static void freeSelectors(void);
static rsRetVal processConfFile(uchar *pConfFile);
static rsRetVal selectorAddList(selector_t *f);
static void processImInternal(void);
/* Code for handling allowed/disallowed senders
*/
#ifdef SYSLOG_INET
static inline void MaskIP6 (struct in6_addr *addr, uint8_t bits) {
register uint8_t i;
assert (addr != NULL);
assert (bits <= 128);
i = bits/32;
if (bits%32)
addr->s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
for (; i < (sizeof addr->s6_addr32)/4; i++)
addr->s6_addr32[i] = 0;
}
static inline void MaskIP4 (struct in_addr *addr, uint8_t bits) {
assert (addr != NULL);
assert (bits <=32 );
addr->s_addr &= htonl(0xffffffff << (32 - bits));
}
#define SIN(sa) ((struct sockaddr_in *)(sa))
#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
/* This function adds an allowed sender entry to the ACL linked list.
* In any case, a single entry is added. If an error occurs, the
* function does its error reporting itself. All validity checks
* must already have been done by the caller.
* This is a helper to AddAllowedSender().
* rgerhards, 2007-07-17
*/
static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
struct NetAddr *iAllow, uint8_t iSignificantBits)
{
struct AllowedSenders *pEntry = NULL;
assert(ppRoot != NULL);
assert(ppLast != NULL);
assert(iAllow != NULL);
if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders))) == NULL) {
glblHadMemShortage = 1;
return RS_RET_OUT_OF_MEMORY; /* no options left :( */
}
memcpy(&(pEntry->allowedSender), iAllow, sizeof (struct NetAddr));
pEntry->pNext = NULL;
pEntry->SignificantBits = iSignificantBits;
/* enqueue */
if(*ppRoot == NULL) {
*ppRoot = pEntry;
} else {
(*ppLast)->pNext = pEntry;
}
*ppLast = pEntry;
return RS_RET_OK;
}
/* function to clear the allowed sender structure in cases where
* it must be freed (occurs most often when HUPed.
* TODO: reconsider recursive implementation
*/
static void clearAllowedSenders (struct AllowedSenders *pAllow) {
if (pAllow != NULL) {
if (pAllow->pNext != NULL)
clearAllowedSenders (pAllow->pNext);
else {
if (F_ISSET(pAllow->allowedSender.flags, ADDR_NAME))
free (pAllow->allowedSender.addr.HostWildcard);
else
free (pAllow->allowedSender.addr.NetAddr);
free (pAllow);
}
}
}
/* function to add an allowed sender to the allowed sender list. The
* root of the list is caller-provided, so it can be used for all
* supported lists. The caller must provide a pointer to the root,
* as it eventually needs to be updated. Also, a pointer to the
* pointer to the last element must be provided (to speed up adding
* list elements).
* rgerhards, 2005-09-26
* If a hostname is given there are possible multiple entries
* added (all addresses from that host).
*/
static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
struct NetAddr *iAllow, uint8_t iSignificantBits)
{
DEFiRet;
assert(ppRoot != NULL);
assert(ppLast != NULL);
assert(iAllow != NULL);
if (!F_ISSET(iAllow->flags, ADDR_NAME)) {
if(iSignificantBits == 0)
/* we handle this seperatly just to provide a better
* error message.
*/
logerror("You can not specify 0 bits of the netmask, this would "
"match ALL systems. If you really intend to do that, "
"remove all $AllowedSender directives.");
|