From f12dd1b777c91d3491505cb2c99feb5987db8edc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 24 Jul 2007 06:11:37 +0000 Subject: moved selector action parsing for F_FORW to omfwd --- omfwd.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) (limited to 'omfwd.c') diff --git a/omfwd.c b/omfwd.c index e38756c6..67aeb792 100644 --- a/omfwd.c +++ b/omfwd.c @@ -37,6 +37,10 @@ #include #include #include +#include +#ifdef USE_PTHREADS +#include +#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: -- cgit