summaryrefslogtreecommitdiffstats
path: root/plugins/imudp/imudp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/imudp/imudp.c')
-rw-r--r--plugins/imudp/imudp.c619
1 files changed, 406 insertions, 213 deletions
diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
index e68bcf37..6abeab07 100644
--- a/plugins/imudp/imudp.c
+++ b/plugins/imudp/imudp.c
@@ -6,7 +6,7 @@
*
* File begun on 2007-12-21 by RGerhards (extracted from syslogd.c)
*
- * Copyright 2007-2009 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2011 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -26,6 +26,7 @@
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
@@ -51,10 +52,12 @@
#include "datetime.h"
#include "prop.h"
#include "ruleset.h"
+#include "statsobj.h"
#include "unicode-helper.h"
MODULE_TYPE_INPUT
MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imudp")
/* defines */
@@ -66,6 +69,16 @@ DEFobjCurrIf(net)
DEFobjCurrIf(datetime)
DEFobjCurrIf(prop)
DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+
+static struct lstn_s {
+ struct lstn_s *next;
+ int sock; /* socket */
+ ruleset_t *pRuleset; /* bound ruleset */
+ statsobj_t *stats; /* listener stats */
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+} *lcnfRoot = NULL, *lcnfLast = NULL;
static int bDoACLCheck; /* are ACL checks neeed? Cached once immediately before listener startup */
static int iMaxLine; /* maximum UDP message size supported */
@@ -73,141 +86,111 @@ static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitte
* This shall prevent remote DoS when the "discard on disallowed sender"
* message is configured to be logged on occurance of such a case.
*/
-static int *udpLstnSocks = NULL; /* Internet datagram sockets, first element is nbr of elements
- * read-only after init(), but beware of restart! */
-static ruleset_t **udpRulesets = NULL; /* ruleset to be used with sockets in question (entry 0 is empty) */
-static uchar *pszBindAddr = NULL; /* IP to bind socket to */
static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a global and alloc
* it so that we can check available memory in willRun() and request
* termination if we can not get it. -- rgerhards, 2007-12-27
*/
static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */
-static uchar *pszSchedPolicy = NULL; /* scheduling policy string */
-static int iSchedPolicy; /* scheduling policy as SCHED_xxx */
-static int iSchedPrio; /* scheduling priority */
-static int seen_iSchedPrio = 0; /* have we seen scheduling priority in the config file? */
-static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */
-#define TIME_REQUERY_DFLT 2
-static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */
-
-/* config settings */
-
-static rsRetVal check_scheduling_priority(int report_error)
-{
- DEFiRet;
-
-#ifdef HAVE_SCHED_GET_PRIORITY_MAX
- if (iSchedPrio < sched_get_priority_min(iSchedPolicy) ||
- iSchedPrio > sched_get_priority_max(iSchedPolicy)) {
- if (report_error)
- errmsg.LogError(errno, NO_ERRCODE,
- "imudp: scheduling priority %d out of range (%d - %d)"
- " for scheduling policy '%s' - ignoring settings",
- iSchedPrio,
- sched_get_priority_min(iSchedPolicy),
- sched_get_priority_max(iSchedPolicy),
- pszSchedPolicy);
- ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
- }
-#endif
-
-finalize_it:
- RETiRet;
-}
-/* Set scheduling priority in the supplied variable (will be iSchedPrio)
- * and record that we have seen the directive (in seen_iSchedPrio).
+#define TIME_REQUERY_DFLT 2
+#define SCHED_PRIO_UNSET -12345678 /* a value that indicates that the scheduling priority has not been set */
+/* config vars for legacy config system */
+static struct configSettings_s {
+ uchar *pszBindAddr; /* IP to bind socket to */
+ uchar *pszSchedPolicy; /* scheduling policy string */
+ uchar *pszBindRuleset; /* name of Ruleset to bind to */
+ int iSchedPrio; /* scheduling priority */
+ int iTimeRequery; /* how often is time to be queried inside tight recv loop? 0=always */
+} cs;
+
+struct instanceConf_s {
+ uchar *pszBindAddr; /* IP to bind socket to */
+ uchar *pszBindPort; /* Port to bind socket to */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ struct instanceConf_s *next;
+};
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ uchar *pszSchedPolicy; /* scheduling policy string */
+ int iSchedPolicy; /* scheduling policy as SCHED_xxx */
+ int iSchedPrio; /* scheduling priority */
+ int iTimeRequery; /* how often is time to be queried inside tight recv loop? 0=always */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+
+
+/* This function is called when a new listener instace shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ * rgerhards, 2011-05-04
*/
-static rsRetVal set_scheduling_priority(void *pVal, int value)
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
{
+ instanceConf_t *inst;
DEFiRet;
- if (seen_iSchedPrio) {
- errmsg.LogError(0, NO_ERRCODE, "directive already seen");
- ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
- }
- *(int *)pVal = value;
- seen_iSchedPrio = 1;
- if (pszSchedPolicy != NULL)
- CHKiRet(check_scheduling_priority(1));
-
-finalize_it:
- RETiRet;
-}
-
-/* Set scheduling policy in iSchedPolicy */
-static rsRetVal set_scheduling_policy(void *pVal, uchar *pNewVal)
-{
- int have_sched_policy = 0;
- DEFiRet;
-
- if (pszSchedPolicy != NULL) {
- errmsg.LogError(0, NO_ERRCODE, "directive already seen");
- ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
+ CHKmalloc(inst = MALLOC(sizeof(instanceConf_t)));
+ CHKmalloc(inst->pszBindPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
+ ? (uchar*) "514" : pNewVal));
+ if((cs.pszBindAddr == NULL) || (cs.pszBindAddr[0] == '\0')) {
+ inst->pszBindAddr = NULL;
+ } else {
+ CHKmalloc(inst->pszBindAddr = ustrdup(cs.pszBindAddr));
}
- *((uchar**)pVal) = pNewVal; /* pVal is pszSchedPolicy */
- if (0) { /* trick to use conditional compilation */
-#ifdef SCHED_FIFO
- } else if (!strcasecmp((char*)pszSchedPolicy, "fifo")) {
- iSchedPolicy = SCHED_FIFO;
- have_sched_policy = 1;
-#endif
-#ifdef SCHED_RR
- } else if (!strcasecmp((char*)pszSchedPolicy, "rr")) {
- iSchedPolicy = SCHED_RR;
- have_sched_policy = 1;
-#endif
-#ifdef SCHED_OTHER
- } else if (!strcasecmp((char*)pszSchedPolicy, "other")) {
- iSchedPolicy = SCHED_OTHER;
- have_sched_policy = 1;
-#endif
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
} else {
- errmsg.LogError(errno, NO_ERRCODE,
- "imudp: invalid scheduling policy '%s' "
- "- ignoring setting", pszSchedPolicy);
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
}
- if (have_sched_policy == 0) {
- free(pszSchedPolicy);
- pszSchedPolicy = NULL;
- ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
+ inst->pBindRuleset = NULL;
+ inst->next = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
}
- if (seen_iSchedPrio)
- CHKiRet(check_scheduling_priority(1));
finalize_it:
+ free(pNewVal);
RETiRet;
}
/* This function is called when a new listener shall be added. It takes
- * the configured parameters, tries to bind the socket and, if that
+ * the instance config description, tries to bind the socket and, if that
* succeeds, adds it to the list of existing listen sockets.
- * rgerhards, 2007-12-27
*/
-static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
+static inline rsRetVal
+addListner(instanceConf_t *inst)
{
DEFiRet;
uchar *bindAddr;
int *newSocks;
- int *tmpSocks;
- int iSrc, iDst;
- ruleset_t **tmpRulesets;
+ int iSrc;
+ struct lstn_s *newlcnfinfo;
+ uchar *bindName;
+ uchar *port;
+ uchar statname[64];
/* check which address to bind to. We could do this more compact, but have not
* done so in order to make the code more readable. -- rgerhards, 2007-12-27
*/
- if(pszBindAddr == NULL)
- bindAddr = NULL;
- else if(pszBindAddr[0] == '*' && pszBindAddr[1] == '\0')
- bindAddr = NULL;
- else
- bindAddr = pszBindAddr;
+#if 0 //<<<<<<< HEAD
- DBGPRINTF("Trying to open syslog UDP ports at %s:%s.\n",
- (bindAddr == NULL) ? (uchar*)"*" : bindAddr, pNewVal);
+ DBGPRINTF("imudp: trying to open port at %s:%s.\n",
+ (inst->pszBindAddr == NULL) ? (uchar*)"*" : inst->pszBindAddr, inst->pszBindPort);
- newSocks = net.create_udp_socket(bindAddr, (pNewVal == NULL || *pNewVal == '\0') ? (uchar*) "514" : pNewVal, 1);
+ newSocks = net.create_udp_socket(inst->pszBindAddr, inst->pszBindPort, 1);
if(newSocks != NULL) {
/* we now need to add the new sockets to the existing set */
if(udpLstnSocks == NULL) {
@@ -215,7 +198,7 @@ static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
udpLstnSocks = newSocks;
CHKmalloc(udpRulesets = (ruleset_t**) MALLOC(sizeof(ruleset_t*) * (newSocks[0] + 1)));
for(iDst = 1 ; iDst <= newSocks[0] ; ++iDst)
- udpRulesets[iDst] = pBindRuleset;
+ udpRulesets[iDst] = inst->pBindRuleset;
} else {
/* we need to add them */
tmpSocks = (int*) MALLOC(sizeof(int) * (1 + newSocks[0] + udpLstnSocks[0]));
@@ -238,7 +221,7 @@ static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
}
for(iSrc = 1 ; iSrc <= newSocks[0] ; ++iSrc, ++iDst) {
tmpSocks[iDst] = newSocks[iSrc];
- tmpRulesets[iDst] = pBindRuleset;
+ tmpRulesets[iDst] = inst->pBindRuleset;
}
tmpSocks[0] = udpLstnSocks[0] + newSocks[0];
free(newSocks);
@@ -247,35 +230,64 @@ static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
free(udpRulesets);
udpRulesets = tmpRulesets;
}
+#else //=======
+ if(inst->pszBindAddr == NULL)
+ bindAddr = NULL;
+ else if(inst->pszBindAddr[0] == '*' && inst->pszBindAddr[1] == '\0')
+ bindAddr = NULL;
+ else
+ bindAddr = inst->pszBindAddr;
+ bindName = (bindAddr == NULL) ? (uchar*)"*" : bindAddr;
+ port = (inst->pszBindPort == NULL || *inst->pszBindPort == '\0') ? (uchar*) "514" : inst->pszBindPort;
+
+ DBGPRINTF("Trying to open syslog UDP ports at %s:%s.\n", bindName, inst->pszBindPort);
+
+ newSocks = net.create_udp_socket(bindAddr, port, 1);
+ if(newSocks != NULL) {
+ /* we now need to add the new sockets to the existing set */
+ /* ready to copy */
+ for(iSrc = 1 ; iSrc <= newSocks[0] ; ++iSrc) {
+ CHKmalloc(newlcnfinfo = (struct lstn_s*) MALLOC(sizeof(struct lstn_s)));
+ newlcnfinfo->next = NULL;
+ newlcnfinfo->sock = newSocks[iSrc];
+ newlcnfinfo->pRuleset = inst->pBindRuleset;
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&(newlcnfinfo->stats)));
+ snprintf((char*)statname, sizeof(statname), "imudp(%s:%s)", bindName, port);
+ statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(statsobj.SetName(newlcnfinfo->stats, statname));
+ STATSCOUNTER_INIT(newlcnfinfo->ctrSubmit, newlcnfinfo->mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(newlcnfinfo->stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, &(newlcnfinfo->ctrSubmit)));
+ CHKiRet(statsobj.ConstructFinalize(newlcnfinfo->stats));
+ /* link to list. Order must be preserved to take care for
+ * conflicting matches.
+ */
+ if(lcnfRoot == NULL)
+ lcnfRoot = newlcnfinfo;
+ if(lcnfLast == NULL)
+ lcnfLast = newlcnfinfo;
+ else {
+ lcnfLast->next = newlcnfinfo;
+ lcnfLast = newlcnfinfo;
+#endif //>>>>>>> ef34821a2737799f48c3032b9616418e4f7fa34f
+ }
}
}
finalize_it:
- free(pNewVal); /* in any case, this is no longer needed */
-
+ free(newSocks);
RETiRet;
}
-/* accept a new ruleset to bind. Checks if it exists and complains, if not */
-static rsRetVal
-setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
{
- ruleset_t *pRuleset;
- rsRetVal localRet;
- DEFiRet;
-
- localRet = ruleset.GetRuleset(&pRuleset, pszName);
- if(localRet == RS_RET_NOT_FOUND) {
- errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName);
- }
- CHKiRet(localRet);
- pBindRuleset = pRuleset;
- DBGPRINTF("imudp current bind ruleset %p: '%s'\n", pRuleset, pszName);
-
-finalize_it:
- free(pszName); /* no longer needed */
- RETiRet;
+ errmsg.LogError(0, NO_ERRCODE, "imudp: ruleset '%s' for %s:%s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszBindAddr == NULL ? "*" : (char*) inst->pszBindAddr,
+ inst->pszBindPort);
}
@@ -294,8 +306,7 @@ finalize_it:
* on scheduling order. -- rgerhards, 2008-10-02
*/
static inline rsRetVal
-processSocket(thrdInfo_t *pThrd, int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
- ruleset_t *pRuleset)
+processSocket(thrdInfo_t *pThrd, struct lstn_s *lstn, struct sockaddr_storage *frominetPrev, int *pbIsPermitted)
{
DEFiRet;
int iNbrTimeUsed;
@@ -315,7 +326,7 @@ processSocket(thrdInfo_t *pThrd, int fd, struct sockaddr_storage *frominetPrev,
if(pThrd->bShallStop == TRUE)
ABORT_FINALIZE(RS_RET_FORCE_TERM);
socklen = sizeof(struct sockaddr_storage);
- lenRcvBuf = recvfrom(fd, (char*) pRcvBuf, iMaxLine, 0, (struct sockaddr *)&frominet, &socklen);
+ lenRcvBuf = recvfrom(lstn->sock, (char*) pRcvBuf, iMaxLine, 0, (struct sockaddr *)&frominet, &socklen);
if(lenRcvBuf < 0) {
if(errno != EINTR && errno != EAGAIN) {
rs_strerror_r(errno, errStr, sizeof(errStr));
@@ -360,23 +371,24 @@ processSocket(thrdInfo_t *pThrd, int fd, struct sockaddr_storage *frominetPrev,
*pbIsPermitted = 1; /* no check -> everything permitted */
}
- DBGPRINTF("recv(%d,%d),acl:%d,msg:%s\n", fd, (int) lenRcvBuf, *pbIsPermitted, pRcvBuf);
+ DBGPRINTF("recv(%d,%d),acl:%d,msg:%s\n", lstn->sock, (int) lenRcvBuf, *pbIsPermitted, pRcvBuf);
if(*pbIsPermitted != 0) {
- if((iTimeRequery == 0) || (iNbrTimeUsed++ % iTimeRequery) == 0) {
+ if((runModConf->iTimeRequery == 0) || (iNbrTimeUsed++ % runModConf->iTimeRequery) == 0) {
datetime.getCurrTime(&stTime, &ttGenTime);
}
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf);
MsgSetInputName(pMsg, pInputName);
- MsgSetRuleset(pMsg, pRuleset);
+ MsgSetRuleset(pMsg, lstn->pRuleset);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME | NEEDS_DNSRESOL;
if(*pbIsPermitted == 2)
pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */
CHKiRet(msgSetFromSockinfo(pMsg, &frominet));
CHKiRet(submitMsg(pMsg));
+ STATSCOUNTER_INC(lstn->ctrSubmit, lstn->mutCtrSubmit);
}
}
@@ -389,42 +401,128 @@ finalize_it:
RETiRet;
}
-static void set_thread_schedparam(void)
+
+/* check configured scheduling priority.
+ * Precondition: iSchedPolicy must have been set
+ */
+static inline rsRetVal
+checkSchedulingPriority(modConfData_t *modConf)
{
- struct sched_param sparam;
+ DEFiRet;
- if (pszSchedPolicy != NULL && seen_iSchedPrio == 0) {
+#ifdef HAVE_SCHED_GET_PRIORITY_MAX
+ if( modConf->iSchedPrio < sched_get_priority_min(modConf->iSchedPolicy)
+ || modConf->iSchedPrio > sched_get_priority_max(modConf->iSchedPolicy)) {
errmsg.LogError(0, NO_ERRCODE,
+ "imudp: scheduling priority %d out of range (%d - %d)"
+ " for scheduling policy '%s' - ignoring settings",
+ modConf->iSchedPrio,
+ sched_get_priority_min(modConf->iSchedPolicy),
+ sched_get_priority_max(modConf->iSchedPolicy),
+ modConf->pszSchedPolicy);
+ ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
+ }
+#endif
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check scheduling policy string and, if valid, set its
+ * numeric equivalent in current load config
+ */
+static rsRetVal
+checkSchedulingPolicy(modConfData_t *modConf)
+{
+ DEFiRet;
+
+ if (0) { /* trick to use conditional compilation */
+#ifdef SCHED_FIFO
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "fifo")) {
+ modConf->iSchedPolicy = SCHED_FIFO;
+#endif
+#ifdef SCHED_RR
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "rr")) {
+ modConf->iSchedPolicy = SCHED_RR;
+#endif
+#ifdef SCHED_OTHER
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "other")) {
+ modConf->iSchedPolicy = SCHED_OTHER;
+#endif
+ } else {
+ errmsg.LogError(errno, NO_ERRCODE,
+ "imudp: invalid scheduling policy '%s' "
+ "- ignoring setting", modConf->pszSchedPolicy);
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* checks scheduling parameters during config check phase */
+static rsRetVal
+checkSchedParam(modConfData_t *modConf)
+{
+ DEFiRet;
+
+ if(modConf->pszSchedPolicy != NULL && modConf->iSchedPrio == SCHED_PRIO_UNSET) {
+ errmsg.LogError(0, RS_RET_ERR_SCHED_PARAMS,
"imudp: scheduling policy set, but without priority - ignoring settings");
- } else if (pszSchedPolicy == NULL && seen_iSchedPrio != 0) {
- errmsg.LogError(0, NO_ERRCODE,
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ } else if(modConf->pszSchedPolicy == NULL && modConf->iSchedPrio != SCHED_PRIO_UNSET) {
+ errmsg.LogError(0, RS_RET_ERR_SCHED_PARAMS,
"imudp: scheduling priority set, but without policy - ignoring settings");
- } else if (pszSchedPolicy != NULL && seen_iSchedPrio != 0 &&
- check_scheduling_priority(0) == 0) {
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ } else if(modConf->pszSchedPolicy != NULL && modConf->iSchedPrio != SCHED_PRIO_UNSET) {
+ /* we have parameters set, so check them */
+ CHKiRet(checkSchedulingPolicy(modConf));
+ CHKiRet(checkSchedulingPriority(modConf));
+ } else { /* nothing set */
+ modConf->iSchedPrio = SCHED_PRIO_UNSET; /* prevents doing the activation call */
+ }
#ifndef HAVE_PTHREAD_SETSCHEDPARAM
- errmsg.LogError(0, NO_ERRCODE,
- "imudp: cannot set thread scheduling policy, "
- "pthread_setschedparam() not available");
-#else
- int err;
-
- memset(&sparam, 0, sizeof sparam);
- sparam.sched_priority = iSchedPrio;
- dbgprintf("imudp trying to set sched policy to '%s', prio %d\n",
- pszSchedPolicy, iSchedPrio);
- err = pthread_setschedparam(pthread_self(), iSchedPolicy, &sparam);
- if (err != 0) {
- errmsg.LogError(err, NO_ERRCODE, "imudp: pthread_setschedparam() failed");
- }
+ errmsg.LogError(0, NO_ERRCODE,
+ "imudp: cannot set thread scheduling policy, "
+ "pthread_setschedparam() not available");
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
#endif
- }
- if (pszSchedPolicy != NULL) {
- free(pszSchedPolicy);
- pszSchedPolicy = NULL;
+finalize_it:
+ if(iRet != RS_RET_OK)
+ modConf->iSchedPrio = SCHED_PRIO_UNSET; /* prevents doing the activation call */
+
+ RETiRet;
+}
+
+/* set the configured scheduling policy (if possible) */
+static rsRetVal
+setSchedParams(modConfData_t *modConf)
+{
+ DEFiRet;
+
+# ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ int err;
+ struct sched_param sparam;
+
+ if(modConf->iSchedPrio == SCHED_PRIO_UNSET)
+ FINALIZE;
+
+ memset(&sparam, 0, sizeof sparam);
+ sparam.sched_priority = modConf->iSchedPrio;
+ dbgprintf("imudp trying to set sched policy to '%s', prio %d\n",
+ modConf->pszSchedPolicy, modConf->iSchedPrio);
+ err = pthread_setschedparam(pthread_self(), modConf->iSchedPolicy, &sparam);
+ if(err != 0) {
+ errmsg.LogError(err, NO_ERRCODE, "imudp: pthread_setschedparam() failed - ignoring");
}
+# endif
+
+finalize_it:
+ RETiRet;
}
+
/* This function implements the main reception loop. Depending on the environment,
* we either use the traditional (but slower) select() or the Linux-specific epoll()
* interface. ./configure settings control which one is used.
@@ -443,15 +541,20 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
struct epoll_event *udpEPollEvt = NULL;
struct epoll_event currEvt[NUM_EPOLL_EVENTS];
char errStr[1024];
+ struct lstn_s *lstn;
+ int nLstn;
/* start "name caching" algo by making sure the previous system indicator
* is invalidated.
*/
- set_thread_schedparam();
bIsPermitted = 0;
memset(&frominetPrev, 0, sizeof(frominetPrev));
- CHKmalloc(udpEPollEvt = calloc(udpLstnSocks[0], sizeof(struct epoll_event)));
+ /* count num listeners -- do it here in order to avoid inconsistency */
+ nLstn = 0;
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next)
+ ++nLstn;
+ CHKmalloc(udpEPollEvt = calloc(nLstn, sizeof(struct epoll_event)));
#if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1)
DBGPRINTF("imudp uses epoll_create1()\n");
@@ -471,16 +574,18 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
/* fill the epoll set - we need to do this only once, as the set
* can not change dyamically.
*/
- for (i = 0; i < *udpLstnSocks; i++) {
- if (udpLstnSocks[i+1] != -1) {
+ i = 0;
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next) {
+ if(lstn->sock != -1) {
udpEPollEvt[i].events = EPOLLIN | EPOLLET;
- udpEPollEvt[i].data.u64 = i+1;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, udpLstnSocks[i+1], &(udpEPollEvt[i])) < 0) {
+ udpEPollEvt[i].data.u64 = (long long unsigned) lstn;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, lstn->sock, &(udpEPollEvt[i])) < 0) {
rs_strerror_r(errno, errStr, sizeof(errStr));
errmsg.LogError(errno, NO_ERRCODE, "epoll_ctrl failed on fd %d with %s\n",
- udpLstnSocks[i+1], errStr);
+ lstn->sock, errStr);
}
}
+ i++;
}
while(1) {
@@ -492,8 +597,7 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
break; /* terminate input! */
for(i = 0 ; i < nfds ; ++i) {
- processSocket(pThrd, udpLstnSocks[currEvt[i].data.u64], &frominetPrev, &bIsPermitted,
- udpRulesets[currEvt[i].data.u64]);
+ processSocket(pThrd, (struct lstn_s*)currEvt[i].data.u64, &frominetPrev, &bIsPermitted);
}
}
@@ -510,36 +614,31 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
DEFiRet;
int maxfds;
int nfds;
- int i;
fd_set readfds;
struct sockaddr_storage frominetPrev;
int bIsPermitted;
+ struct lstn_s *lstn;
/* start "name caching" algo by making sure the previous system indicator
* is invalidated.
*/
- set_thread_schedparam();
bIsPermitted = 0;
memset(&frominetPrev, 0, sizeof(frominetPrev));
DBGPRINTF("imudp uses select()\n");
while(1) {
- /* Add the Unix Domain Sockets to the list of read
- * descriptors.
- * rgerhards 2005-08-01: we must now check if there are
- * any local sockets to listen to at all. If the -o option
- * is given without -a, we do not need to listen at all..
+ /* Add the Unix Domain Sockets to the list of read descriptors.
*/
maxfds = 0;
FD_ZERO(&readfds);
/* Add the UDP listen sockets to the list of read descriptors. */
- for (i = 0; i < *udpLstnSocks; i++) {
- if (udpLstnSocks[i+1] != -1) {
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next) {
+ if (lstn->sock != -1) {
if(Debug)
- net.debugListenInfo(udpLstnSocks[i+1], "UDP");
- FD_SET(udpLstnSocks[i+1], &readfds);
- if(udpLstnSocks[i+1]>maxfds) maxfds=udpLstnSocks[i+1];
+ net.debugListenInfo(lstn->sock, "UDP");
+ FD_SET(lstn->sock, &readfds);
+ if(lstn->sock>maxfds) maxfds=lstn->sock;
}
}
if(Debug) {
@@ -555,10 +654,9 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
if(glbl.GetGlobalInputTermState() == 1)
break; /* terminate input! */
- for(i = 0; nfds && i < *udpLstnSocks; i++) {
- if(FD_ISSET(udpLstnSocks[i+1], &readfds)) {
- processSocket(pThrd, udpLstnSocks[i+1], &frominetPrev, &bIsPermitted,
- udpRulesets[i+1]);
+ for(lstn = lcnfRoot ; nfds && lstn != NULL ; lstn = lstn->next) {
+ if(FD_ISSET(lstn->sock, &readfds)) {
+ processSocket(pThrd, lstn, &frominetPrev, &bIsPermitted);
--nfds; /* indicate we have processed one descriptor */
}
}
@@ -569,8 +667,95 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd)
}
#endif /* #if HAVE_EPOLL_CREATE1 */
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init legacy config vars */
+ cs.pszBindRuleset = NULL;
+ cs.pszSchedPolicy = NULL;
+ cs.pszBindAddr = NULL;
+ cs.iSchedPrio = SCHED_PRIO_UNSET;
+ cs.iTimeRequery = TIME_REQUERY_DFLT;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ /* persist module-specific settings from legacy config system
+ * TODO: when we add the new config system, we must decide on priority
+ * already-set module options should not be overwritable by the legacy
+ * system (though this is debatable and should at least trigger an error
+ * message if the equivalent legacy option is selected as well)
+ * rgerhards, 2011-05-04
+ */
+ loadModConf->iSchedPrio = cs.iSchedPrio;
+ loadModConf->iTimeRequery = cs.iTimeRequery;
+ if((cs.pszSchedPolicy == NULL) || (cs.pszSchedPolicy[0] == '\0')) {
+ loadModConf->pszSchedPolicy = NULL;
+ } else {
+ CHKmalloc(loadModConf->pszSchedPolicy = ustrdup(cs.pszSchedPolicy));
+ }
+
+finalize_it:
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pszBindRuleset);
+ free(cs.pszSchedPolicy);
+ free(cs.pszBindAddr);
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ checkSchedParam(pModConf); /* this can not cause fatal errors */
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ if(pModConf->root == NULL) {
+ errmsg.LogError(0, RS_RET_NO_LISTNERS , "imudp: module loaded, but "
+ "no listeners defined - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(inst);
+ }
+ /* if we could not set up any listners, there is no point in running... */
+ if(lcnfRoot == NULL) {
+ errmsg.LogError(0, NO_ERRCODE, "imudp: no listeners could be started, "
+ "input not activated.\n");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ setSchedParams(pModConf);
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ /* caching various settings */
+ iMaxLine = glbl.GetMaxLine();
+ CHKmalloc(pRcvBuf = MALLOC((iMaxLine + 1) * sizeof(char)));
+finalize_it:
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
/* This function is called to gather input.
- * Note that udpLstnSocks must be non-NULL because otherwise we would not have
+ * Note that sock must be non-NULL because otherwise we would not have
* indicated that we want to run (or we have a programming error ;)). -- rgerhards, 2008-10-02
*/
BEGINrunInput
@@ -582,49 +767,40 @@ ENDrunInput
/* initialize and return if will run or not */
BEGINwillRun
CODESTARTwillRun
- /* we need to create the inputName property (only once during our lifetime) */
- CHKiRet(prop.Construct(&pInputName));
- CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1));
- CHKiRet(prop.ConstructFinalize(pInputName));
-
net.PrintAllowedSenders(1); /* UDP */
net.HasRestrictions(UCHAR_CONSTANT("UDP"), &bDoACLCheck); /* UDP */
-
- /* if we could not set up any listners, there is no point in running... */
- if(udpLstnSocks == NULL)
- ABORT_FINALIZE(RS_RET_NO_RUN);
-
- iMaxLine = glbl.GetMaxLine();
-
- CHKmalloc(pRcvBuf = MALLOC((iMaxLine + 1) * sizeof(char)));
-finalize_it:
ENDwillRun
BEGINafterRun
+ struct lstn_s *lstn, *lstnDel;
CODESTARTafterRun
/* do cleanup here */
net.clearAllowedSenders((uchar*)"UDP");
- if(udpLstnSocks != NULL) {
- net.closeUDPListenSockets(udpLstnSocks);
- udpLstnSocks = NULL;
- free(udpRulesets);
- udpRulesets = NULL;
+ for(lstn = lcnfRoot ; lstn != NULL ; ) {
+ statsobj.Destruct(&(lstn->stats));
+ close(lstn->sock);
+ lstnDel = lstn;
+ lstn = lstn->next;
+ free(lstnDel);
}
+ lcnfRoot = lcnfLast = NULL;
if(pRcvBuf != NULL) {
free(pRcvBuf);
pRcvBuf = NULL;
}
- if(pInputName != NULL)
- prop.Destruct(&pInputName);
ENDafterRun
BEGINmodExit
CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
/* release what we no longer need */
objRelease(errmsg, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
objRelease(prop, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
@@ -642,16 +818,27 @@ ENDisCompatibleWithFeature
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
ENDqueryEtryPt
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
- if(pszBindAddr != NULL) {
- free(pszBindAddr);
- pszBindAddr = NULL;
+ if(cs.pszBindAddr != NULL) {
+ free(cs.pszBindAddr);
+ cs.pszBindAddr = NULL;
+ }
+ if(cs.pszSchedPolicy != NULL) {
+ free(cs.pszSchedPolicy);
+ cs.pszSchedPolicy = NULL;
+ }
+ if(cs.pszBindRuleset != NULL) {
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
}
- iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */
+ cs.iSchedPrio = SCHED_PRIO_UNSET;
+ cs.iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */
return RS_RET_OK;
}
@@ -662,24 +849,30 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(prop, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
/* register config file handlers */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputudpserverbindruleset", 0, eCmdHdlrGetWord,
- setRuleset, NULL, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserverrun", 0, eCmdHdlrGetWord,
- addListner, NULL, STD_LOADABLE_MODULE_ID));
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserveraddress", 0, eCmdHdlrGetWord,
- NULL, &pszBindAddr, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.pszBindAddr, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imudpschedulingpolicy", 0, eCmdHdlrGetWord,
- &set_scheduling_policy, NULL, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.pszSchedPolicy, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imudpschedulingpriority", 0, eCmdHdlrInt,
- &set_scheduling_priority, NULL, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.iSchedPrio, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpservertimerequery", 0, eCmdHdlrInt,
- NULL, &iTimeRequery, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.iTimeRequery, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit