summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parse.c180
-rw-r--r--parse.h7
-rw-r--r--rsyslog.h3
-rw-r--r--syslogd.c141
4 files changed, 279 insertions, 52 deletions
diff --git a/parse.c b/parse.c
index 51737278..a2eb9ce3 100644
--- a/parse.c
+++ b/parse.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
+#include <arpa/inet.h>
#include "rsyslog.h"
#include "parse.h"
@@ -26,6 +27,21 @@
/**
+ * Destruct a rsPars object and its associated string.
+ * rgerhards, 2005-09-26
+ */
+rsRetVal rsParsDestruct(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if(pThis->pCStr != NULL)
+ RSFREEOBJ(pThis->pCStr);
+ RSFREEOBJ(pThis);
+ return RS_RET_OK;
+}
+
+
+/**
* Construct a rsPars object.
*/
rsRetVal rsParsConstruct(rsParsObj **ppThis)
@@ -44,6 +60,40 @@ rsRetVal rsParsConstruct(rsParsObj **ppThis)
}
/**
+ * Construct a rsPars object and populate it with a
+ * classical zero-terinated C-String.
+ * rgerhards, 2005-09-27
+ */
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, char *psz)
+{
+ rsParsObj *pThis;
+ rsCStrObj *pCS;
+ rsRetVal iRet;
+
+ assert(ppThis != NULL);
+ assert(psz != NULL);
+
+ /* create string for parser */
+ if((iRet = rsCStrConstructFromszStr(&pCS, psz)) != RS_RET_OK)
+ return(iRet);
+
+ /* create parser */
+ if((iRet = rsParsConstruct(&pThis)) != RS_RET_OK) {
+ RSFREEOBJ(pCS);
+ return(iRet);
+ }
+
+ /* assign string to parser */
+ if((iRet = rsParsAssignString(pThis, pCS)) != RS_RET_OK) {
+ rsParsDestruct(pThis);
+ return(iRet);
+ }
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+/**
* Assign the to-be-parsed string.
*/
rsRetVal rsParsAssignString(rsParsObj *pThis, rsCStrObj *pCStr)
@@ -57,12 +107,42 @@ rsRetVal rsParsAssignString(rsParsObj *pThis, rsCStrObj *pCStr)
return RS_RET_OK;
}
-/* parse an integer. The parse pointer is advanced */
+/* parse an integer. The parse pointer is advanced to the
+ * position directly after the last digit. If no digit is
+ * found at all, an error is returned and the parse pointer
+ * is NOT advanced.
+ * PORTABILITY WARNING: this function depends on the
+ * continues representation of digits inside the character
+ * set (as in ASCII).
+ * rgerhards 2005-09-27
+ */
rsRetVal parsInt(rsParsObj *pThis, int* pInt)
{
+ char *pC;
+ int iVal;
+
rsCHECKVALIDOBJECT(pThis, OIDrsPars);
assert(pInt != NULL);
+ iVal = 0;
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* order of checks is important, else we might do
+ * mis-addressing! (off by one)
+ */
+ if(pThis->iCurrPos >= rsCStrLen(pThis->pCStr))
+ return RS_RET_NO_MORE_DATA;
+ if(!isdigit(*pC))
+ return RS_RET_NO_DIGIT;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && isdigit(*pC)) {
+ iVal = iVal * 10 + *pC - '0';
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ *pInt = iVal;
+
return RS_RET_OK;
}
@@ -263,6 +343,104 @@ rsRetVal parsQuotedCStr(rsParsObj *pThis, rsCStrObj **ppCStr)
return RS_RET_OK;
}
+/* Parse an IPv4-Adress with optional "mask-bits" in the
+ * format "a.b.c.d/bits" (e.g. "192.168.0.0/24"). The parsed
+ * IP (in HOST byte order!) as well as the mask bits are returned. Leading and
+ * trailing whitespace is ignored. The function moves the parse
+ * pointer to the next non-whitespace, non-comma character after the address.
+ * rgerhards, 2005-09-27
+ */
+rsRetVal parsIPv4WithBits(rsParsObj *pThis, unsigned long *pIP, int *pBits)
+{
+ register char *pC;
+ char *pszIP;
+ rsCStrObj *pCStr;
+ rsRetVal iRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pIP != NULL);
+ assert(pBits != NULL);
+
+ if((pCStr = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ parsSkipWhitespace(pThis);
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* we parse everything until either '/', ',' or
+ * whitespace. Validity will be checked down below.
+ */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && *pC != '/' && *pC != ',' && !isspace(*pC)) {
+ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ RSFREEOBJ(pCStr);
+ return(iRet);
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ /* We got the string, let's finish it... */
+ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
+ RSFREEOBJ(pCStr);
+ return(iRet);
+ }
+
+ /* now we have the string and must check/convert it to
+ * an IPv4 address in host byte order.
+ */
+ if(rsCStrLen(pCStr) < 7) {
+ /* 7 ist the minimum length of an IPv4 address (1.2.3.4) */
+ RSFREEOBJ(pCStr);
+ return RS_RET_INVALID_IP;
+ }
+
+ if((pszIP = rsCStrConvSzStrAndDestruct(pCStr)) == NULL)
+ return RS_RET_ERR;
+
+ if((*pIP = inet_addr(pszIP)) == -1) {
+ free(pszIP);
+ return RS_RET_INVALID_IP;
+ }
+ *pIP = ntohl(*pIP); /* convert to host byte order */
+ free(pszIP); /* no longer needed */
+
+ if(*pC == '/') {
+ /* mask bits follow, let's parse them! */
+ ++pThis->iCurrPos; /* eat slash */
+ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
+ return(iRet);
+ }
+ /* we need to refresh pointer (changed by parsInt()) */
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+ } else {
+ /* no slash, so we assume a single host (/32) */
+ *pBits = 32;
+ }
+
+ /* skip to next processable character */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && (*pC == ',' || isspace(*pC))) {
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ return RS_RET_OK;
+}
+
+
+/* tell if the parsepointer is at the end of the
+ * to-be-parsed string. Returns 1, if so, 0
+ * otherwise. rgerhards, 2005-09-27
+ */
+int parsIsAtEndOfParseString(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ return (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) ? 0 : 1;
+}
+
+
/* return the position of the parse pointer
*/
int rsParsGetParsePointer(rsParsObj *pThis)
diff --git a/parse.h b/parse.h
index 6bbc4afd..c3e2733f 100644
--- a/parse.h
+++ b/parse.h
@@ -76,7 +76,12 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, rsCStrObj **ppCStr, char cDelim, int bT
rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c);
rsRetVal parsQuotedCStr(rsParsObj *pThis, rsCStrObj **ppCStr);
-#if 0 /* later! */
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, char *psz);
+rsRetVal rsParsDestruct(rsParsObj *pThis);
+rsRetVal parsIPv4WithBits(rsParsObj *pThis, unsigned long *pIP, int *pBits);
+int parsIsAtEndOfParseString(rsParsObj *pThis);
+
+#if 0 /* later! - but leave it in in case we need it some day... */
/* Parse a property
* This is a complex parsing routine. It parses an property
* entry suitable for use in the property replacer. It is currently
diff --git a/rsyslog.h b/rsyslog.h
index ccd5db89..d2775619 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -36,6 +36,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_FOUND_AT_STRING_END = -3002, /**< some value found, but at the last pos of string */
RS_RET_NOT_FOUND = -3003, /**< some requested value not found */
RS_RET_MISSING_TRAIL_QUOTE = -3004, /**< an expected trailing quote is missing */
+ RS_RET_NO_DIGIT = -3005, /**< an digit was expected, but none found (mostly parsing) */
+ RS_RET_NO_MORE_DATA = -3006, /**< insufficient data, e.g. end of string during parsing */
+ RS_RET_INVALID_IP = -3007, /**< invalid ip found where valid was expected */
RS_RET_OK = 0 /**< operation successful */
};
typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
diff --git a/syslogd.c b/syslogd.c
index a5cecaba..fc45a60a 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -362,7 +362,7 @@ const char *directive_name_list[] = {
};
/* ... and their definitions: */
enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1,
- DIR_ALLOWEDUDPSENDER = 2, DIR_ALLOWEDTCPSENDER = 3};
+ DIR_ALLOWEDSENDER = 2};
/* rgerhards 2004-11-11: the following structure represents
* a time as it is used in syslog.
@@ -748,11 +748,9 @@ static int create_udp_socket();
* 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).
- * returns 1 if sender could be added, 0 otherwise (this probably indicates
- * big trouble with the memory allocator).
* rgerhards, 2005-09-26
*/
-static int AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
+static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
unsigned int iAllow, int iSignificantBits)
{
struct AllowedSenders *pEntry;
@@ -762,7 +760,7 @@ static int AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSender
if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders)))
== NULL)
- return 0; /* no options left :( */
+ return RS_RET_OUT_OF_MEMORY; /* no options left :( */
/* populate entry */
pEntry->bitsToShift = 32 - iSignificantBits; /* IPv4! */
@@ -777,7 +775,7 @@ static int AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSender
}
*ppLast = pEntry;
- return 1;
+ return RS_RET_OK;
}
#endif /* #ifdef SYSLOG_INET */
@@ -2524,6 +2522,9 @@ int main(int argc, char **argv)
#ifndef NOLARGEFILE
printf("\tFEATURE_LARGEFILE\n");
#endif
+#ifdef SYSLOG_INET
+ printf("\tSYSLOG_INET (Internet/remote support)\n");
+#endif
#ifndef NDEBUG
printf("\tFEATURE_DEBUG (debug build, slow code)\n");
#endif
@@ -2539,8 +2540,6 @@ int main(int argc, char **argv)
if ((argc -= optind))
usage();
-printf("Test addAllowed %d\n", AddAllowedSender(&pAllowedSenders_UDP, &pLastAllowedSenders_UDP,
- 0xac120000, 16));
#ifndef TESTING
if ( !(Debug || NoFork) )
{
@@ -3672,7 +3671,6 @@ void logmsg(int pri, struct msg *pMsg, int flags)
* 2005-09-19 rgerhards
*/
if(!shouldProcessThisMessage(f, pMsg)) {
- dprintf("message filter does not match - ignoring selector line\n");
continue;
}
@@ -4775,6 +4773,77 @@ void doexit(sig)
}
#endif
+
+/* parse an allowed sender config line and add the allowed senders
+ * (if the line is correct).
+ * rgerhards, 2005-09-27
+ */
+rsRetVal addAllowedSenderLine(char* pName, char** ppRestOfConfLine)
+{
+ struct AllowedSenders **ppRoot;
+ struct AllowedSenders **ppLast;
+ rsParsObj *pPars;
+ rsRetVal iRet;
+ unsigned long uIP;
+ int iBits;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+ assert(*ppRestOfConfLine != NULL);
+
+#ifndef SYSLOG_INET
+ errno = 0;
+ logerror("config file contains allowed sender list, but rsyslogd "
+ "compiled without Internet support - line ignored");
+#else
+ if(!strcasecmp(pName, "udp")) {
+ ppRoot = &pAllowedSenders_UDP;
+ ppLast = &pLastAllowedSenders_UDP;
+ } else if(!strcasecmp(pName, "tcp")) {
+ ppRoot = &pAllowedSenders_TCP;
+ ppLast = &pLastAllowedSenders_TCP;
+ } else {
+ logerrorSz("Invalid protocol '%s' in allowed sender "
+ "list, line ignored", pName);
+ return RS_RET_ERR;
+ }
+
+printf("addAllow..., name '%s', line: '%s'\n", pName, *ppRestOfConfLine);
+ /* OK, we now know the protocol and have valid list pointers.
+ * So let's process the entries. We are using the parse class
+ * for this.
+ */
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, *ppRestOfConfLine) != RS_RET_OK)) {
+ logerrorInt("Error %d constructing parser object - ignoring allowed sender list", iRet);
+ return(iRet);
+ }
+
+ while(!parsIsAtEndOfParseString(pPars)) {
+ /* now parse a single IP address */
+ if((iRet = parsIPv4WithBits(pPars, &uIP, &iBits)) != RS_RET_OK) {
+ logerrorInt("Error %d parsing IP address in allowed sender"
+ "list - ignoring.", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+ printf("returned IP %x, bits %d\n", uIP, iBits);
+ if((iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits))
+ != RS_RET_OK) {
+ logerrorInt("Error %d adding allowed sender entry "
+ "- ignoring.", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+
+ }
+
+ /* cleanup */
+ return rsParsDestruct(pPars);
+#endif /*#ifndef SYSLOG_INET */
+}
+
+
/* parse and interpret a $-config line that starts with
* a name (this is common code). It is parsed to the name
* and then the proper sub-function is called to handle
@@ -4791,7 +4860,7 @@ void doNameLine(char **pp, enum eDirective eDir)
assert(pp != NULL);
assert(p != NULL);
assert( (eDir == DIR_TEMPLATE) || (eDir == DIR_OUTCHANNEL)
- || (eDir == DIR_ALLOWEDUDPSENDER) || (eDir == DIR_ALLOWEDTCPSENDER));
+ || (eDir == DIR_ALLOWEDSENDER));
if(getSubString(&p, szName, sizeof(szName) / sizeof(char), ',') != 0) {
char errMsg[128];
@@ -4817,11 +4886,8 @@ void doNameLine(char **pp, enum eDirective eDir)
case DIR_OUTCHANNEL:
ochAddLine(szName, &p);
break;
- case DIR_ALLOWEDUDPSENDER:
- // TODO: addUDPSender(szName, &p);
- break;
- case DIR_ALLOWEDTCPSENDER:
- // TODO: addTCPSender(szName, &p);
+ case DIR_ALLOWEDSENDER:
+ addAllowedSenderLine(szName, &p);
break;
}
@@ -4852,10 +4918,8 @@ void cfsysline(char *p)
doNameLine(&p, DIR_TEMPLATE);
} else if(!strcasecmp(szCmd, "outchannel")) {
doNameLine(&p, DIR_OUTCHANNEL);
- } else if(!strcasecmp(szCmd, "allowedudpsender")) {
- doNameLine(&p, DIR_ALLOWEDUDPSENDER);
- } else if(!strcasecmp(szCmd, "allowedtcpsender")) {
- doNameLine(&p, DIR_ALLOWEDTCPSENDER);
+ } else if(!strcasecmp(szCmd, "allowedsender")) {
+ doNameLine(&p, DIR_ALLOWEDSENDER);
} else { /* invalid command! */
char err[100];
snprintf(err, sizeof(err)/sizeof(char),
@@ -5553,7 +5617,6 @@ rsRetVal cflineProcessTradPRIFilter(char **pline, register struct filed *f)
rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
{
rsParsObj *pPars;
- rsCStrObj *pCSLine;
rsCStrObj *pCSCompOp;
rsRetVal iRet;
int iOffset; /* for compare operations */
@@ -5567,23 +5630,9 @@ rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
f->f_filter_type = FILTER_PROP;
- /* create line string without leading colon */
- if((iRet = rsCStrConstructFromszStr(&pCSLine, (*pline)+1)) != RS_RET_OK) {
- logerrorInt("Error %d allocating string space - ignoring selector", iRet);
- return(iRet);
- }
-
- /* create parser */
- if((iRet = rsParsConstruct(&pPars)) != RS_RET_OK) {
- logerrorInt("error %d creating parser - ignoring selector", iRet);
- RSFREEOBJ(pCSLine);
- return(iRet);
- }
-
- if((iRet = rsParsAssignString(pPars, pCSLine)) != RS_RET_OK) {
- logerrorInt("error %d assigning string to parser - ignoring selector", iRet);
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, (*pline)+1)) != RS_RET_OK) {
+ logerrorInt("Error %d constructing parser object - ignoring selector", iRet);
return(iRet);
}
@@ -5591,8 +5640,7 @@ rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1);
if(iRet != RS_RET_OK) {
logerrorInt("error %d parsing filter property - ignoring selector", iRet);
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
+ rsParsDestruct(pPars);
return(iRet);
}
@@ -5600,8 +5648,7 @@ rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1);
if(iRet != RS_RET_OK) {
logerrorInt("error %d compare operation property - ignoring selector", iRet);
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
+ rsParsDestruct(pPars);
return(iRet);
}
@@ -5639,17 +5686,14 @@ rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
if(iRet != RS_RET_OK) {
logerrorInt("error %d compare value property - ignoring selector", iRet);
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
+ rsParsDestruct(pPars);
return(iRet);
}
- printf("after read CompVal, prop name '%s'\n", rsCStrGetSzStr(f->f_filterData.prop.pCSCompValue));
/* skip to action part */
if((iRet = parsSkipWhitespace(pPars)) != RS_RET_OK) {
logerrorInt("error %d skipping to action part - ignoring selector", iRet);
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
+ rsParsDestruct(pPars);
return(iRet);
}
@@ -5657,10 +5701,7 @@ rsRetVal cflineProcessPropFilter(char **pline, register struct filed *f)
*pline = *pline + rsParsGetParsePointer(pPars) + 1;
/* we are adding one for the skipped initial ":" */
- RSFREEOBJ(pPars);
- RSFREEOBJ(pCSLine);
-
- return RS_RET_OK;
+ return rsParsDestruct(pPars);
}