summaryrefslogtreecommitdiffstats
path: root/omfwd.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2007-07-24 06:11:37 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2007-07-24 06:11:37 +0000
commitf12dd1b777c91d3491505cb2c99feb5987db8edc (patch)
treef6bc2ba9a3f222b29240176e03873488785a28f1 /omfwd.c
parentfe0da1ef850dc9e93993f8332a87cbf815cea2f7 (diff)
downloadrsyslog-f12dd1b777c91d3491505cb2c99feb5987db8edc.tar.gz
rsyslog-f12dd1b777c91d3491505cb2c99feb5987db8edc.tar.xz
rsyslog-f12dd1b777c91d3491505cb2c99feb5987db8edc.zip
moved selector action parsing for F_FORW to omfwd
Diffstat (limited to 'omfwd.c')
-rw-r--r--omfwd.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/omfwd.c b/omfwd.c
index e38756c6..67aeb792 100644
--- a/omfwd.c
+++ b/omfwd.c
@@ -37,6 +37,10 @@
#include <fnmatch.h>
#include <assert.h>
#include <errno.h>
+#include <ctype.h>
+#ifdef USE_PTHREADS
+#include <pthread.h>
+#endif
#include "rsyslog.h"
#include "syslogd.h"
#include "syslogd-types.h"
@@ -273,6 +277,200 @@ rsRetVal modInitFwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersP
*pQueryEtryPt = queryEtryPt;
return RS_RET_OK;
}
+
+
+/* try to process a selector action line. Checks if the action
+ * applies to this module and, if so, processed it. If not, it
+ * is left untouched. The driver will then call another module
+ */
+rsRetVal parseSelectorActFwd(uchar **pp, selector_t *f)
+{
+ uchar *p, *q;
+ int i;
+ int error;
+ int bErr;
+ rsRetVal iRet = RS_RET_CONFLINE_PROCESSED;
+ struct addrinfo hints, *res;
+ char szTemplateName[128];
+
+ assert(pp != NULL);
+ assert(f != NULL);
+
+ p = *pp;
+
+ switch (*p)
+ {
+ case '@':
+ ++p; /* eat '@' */
+ if(*p == '@') { /* indicator for TCP! */
+ f->f_un.f_forw.protocol = FORW_TCP;
+ ++p; /* eat this '@', too */
+ /* in this case, we also need a mutex... */
+# ifdef USE_PTHREADS
+ pthread_mutex_init(&f->f_un.f_forw.mtxTCPSend, 0);
+# endif
+ } else {
+ f->f_un.f_forw.protocol = FORW_UDP;
+ }
+ /* we are now after the protocol indicator. Now check if we should
+ * use compression. We begin to use a new option format for this:
+ * @(option,option)host:port
+ * The first option defined is "z[0..9]" where the digit indicates
+ * the compression level. If it is not given, 9 (best compression) is
+ * assumed. An example action statement might be:
+ * @@(z5,o)127.0.0.1:1400
+ * Which means send via TCP with medium (5) compresion (z) to the local
+ * host on port 1400. The '0' option means that octet-couting (as in
+ * IETF I-D syslog-transport-tls) is to be used for framing (this option
+ * applies to TCP-based syslog only and is ignored when specified with UDP).
+ * That is not yet implemented.
+ * rgerhards, 2006-12-07
+ */
+ if(*p == '(') {
+ /* at this position, it *must* be an option indicator */
+ do {
+ ++p; /* eat '(' or ',' (depending on when called) */
+ /* check options */
+ if(*p == 'z') { /* compression */
+# ifdef USE_NETZIP
+ ++p; /* eat */
+ if(isdigit((int) *p)) {
+ int iLevel;
+ iLevel = *p - '0';
+ ++p; /* eat */
+ f->f_un.f_forw.compressionLevel = iLevel;
+ } else {
+ logerrorInt("Invalid compression level '%c' specified in "
+ "forwardig action - NOT turning on compression.",
+ *p);
+ }
+# else
+ logerror("Compression requested, but rsyslogd is not compiled "
+ "with compression support - request ignored.");
+# endif /* #ifdef USE_NETZIP */
+ } else if(*p == 'o') { /* octet-couting based TCP framing? */
+ ++p; /* eat */
+ /* no further options settable */
+ f->f_un.f_forw.tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else { /* invalid option! Just skip it... */
+ logerrorInt("Invalid option %c in forwarding action - ignoring.", *p);
+ ++p; /* eat invalid option */
+ }
+ /* the option processing is done. We now do a generic skip
+ * to either the next option or the end of the option
+ * block.
+ */
+ while(*p && *p != ')' && *p != ',')
+ ++p; /* just skip it */
+ } while(*p && *p == ','); /* Attention: do.. while() */
+ if(*p == ')')
+ ++p; /* eat terminator, on to next */
+ else
+ /* we probably have end of string - leave it for the rest
+ * of the code to handle it (but warn the user)
+ */
+ logerror("Option block not terminated in forwarding action.");
+ }
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
+ /* JUST SKIP */;
+
+ f->f_un.f_forw.port = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ f->f_un.f_forw.port = malloc(i + 1);
+ if(f->f_un.f_forw.port == NULL) {
+ logerror("Could not get memory to store syslog forwarding port, "
+ "using default port, results may not be what you intend\n");
+ /* we leave f_forw.port set to NULL, this is then handled by
+ * getFwdSyslogPt().
+ */
+ } else {
+ memcpy(f->f_un.f_forw.port, tmp, i);
+ *(f->f_un.f_forw.port + i) = '\0';
+ }
+ }
+
+ /* now skip to template */
+ bErr = 0;
+ while(*p && *p != ';') {
+ if(*p && *p != ';' && !isspace((int) *p)) {
+ if(bErr == 0) { /* only 1 error msg! */
+ bErr = 1;
+ errno = 0;
+ logerror("invalid selector line (port), probably not doing "
+ "what was intended");
+ }
+ }
+ ++p;
+ }
+
+ if(*p == ';') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ ++p;
+ /* Now look for the template! */
+ cflineParseTemplateName(&p, szTemplateName,
+ sizeof(szTemplateName) / sizeof(char));
+ } else
+ szTemplateName[0] = '\0';
+ if(szTemplateName[0] == '\0') {
+ /* we do not have a template, so let's use the default */
+ strcpy(szTemplateName, " StdFwdFmt");
+ }
+
+ /* first set the f->f_type */
+ strcpy(f->f_un.f_forw.f_hname, (char*) q);
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requests this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = family;
+ hints.ai_socktype = f->f_un.f_forw.protocol == FORW_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ f->doAction = doActionFwd;
+ if( (error = getaddrinfo(f->f_un.f_forw.f_hname, getFwdSyslogPt(f), &hints, &res)) != 0) {
+ f->f_type = F_FORW_UNKN;
+ f->f_prevcount = INET_RETRY_MAX;
+ f->f_un.f_forw.ttSuspend = time(NULL);
+ } else {
+ f->f_type = F_FORW;
+ f->f_un.f_forw.f_addr = res;
+ }
+
+ /* then try to find the template and re-set f_type to UNUSED
+ * if it can not be found. */
+ cflineSetTemplateAndIOV(f, szTemplateName);
+ if(f->f_type == F_UNUSED)
+ /* safety measure to make sure we have a valid
+ * selector line before we continue down below.
+ * rgerhards 2005-07-29
+ */
+ break;
+
+ dprintf("forwarding host: '%s:%s/%s' template '%s'\n", q, getFwdSyslogPt(f),
+ f->f_un.f_forw.protocol == FORW_UDP ? "udp" : "tcp",
+ szTemplateName);
+ /*
+ * Otherwise the host might be unknown due to an
+ * inaccessible nameserver (perhaps on the same
+ * host). We try to get the ip number later, like
+ * FORW_SUSP.
+ */
+ default:
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ break;
+ }
+
+ if(iRet == RS_RET_CONFLINE_PROCESSED)
+ *pp = p;
+ return iRet;
+}
+
#endif /* #ifdef SYSLOG_INET */
/*
* vi:set ai: