diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2007-07-19 16:06:17 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2007-07-19 16:06:17 +0000 |
commit | f2dcce7ce53aeb7679e0e0af40d59c0efb3062cc (patch) | |
tree | 97518364e3b3bd1bfbdefab2d9ec66ce54a4a836 | |
parent | 3a58c0b3191476851487e55f8db4b0deb99f7b10 (diff) | |
download | rsyslog-f2dcce7ce53aeb7679e0e0af40d59c0efb3062cc.tar.gz rsyslog-f2dcce7ce53aeb7679e0e0af40d59c0efb3062cc.tar.xz rsyslog-f2dcce7ce53aeb7679e0e0af40d59c0efb3062cc.zip |
moved message object into its own set of files
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | msg.c | 1041 | ||||
-rw-r--r-- | msg.h | 150 | ||||
-rw-r--r-- | syslogd-types.h | 81 | ||||
-rw-r--r-- | syslogd.c | 1059 | ||||
-rw-r--r-- | syslogd.h | 36 |
7 files changed, 1269 insertions, 1102 deletions
@@ -9,6 +9,8 @@ Version 1.17.1 (RGer), 2007-07-?? - fixed minimal memory leak on HUP (caused by templates) thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch - code cleanup (removed compiler warnings) +- fixed portability bug in configure.ac - thanks to Bartosz Kuźma for patch +- moved msg object into its own file set --------------------------------------------------------------------------- Version 1.17.0 (RGer), 2007-07-17 - added $RepeatedLineReduction config parameter diff --git a/Makefile.am b/Makefile.am index e85307dd..e4d7ff24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ rfc3195d_SOURCES=rfc3195d.c rsyslog.h man_MANS = rfc3195d.8 rklogd.8 rsyslogd.8 rsyslog.conf.5 -rsyslogd_SOURCES=syslogd.c pidfile.c template.c outchannel.c stringbuf.c srUtils.c parse.c syslogd-types.h template.h outchannel.h syslogd.h stringbuf.h parse.h srUtils.h liblogging-stub.h net.h +rsyslogd_SOURCES=syslogd.c pidfile.c template.c outchannel.c stringbuf.c srUtils.c parse.c syslogd-types.h template.h outchannel.h syslogd.h stringbuf.h parse.h srUtils.h liblogging-stub.h net.h msg.c msg.h rsyslogd_CPPFLAGS=$(mysql_includes) rsyslogd_LDADD=$(mysql_libs) $(zlib_libs) $(pthreads_libs) @@ -0,0 +1,1041 @@ +/* msg.c + * The msg object. Implementation of all msg-related functions + * + * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) + * This file is under development and has not yet arrived at being fully + * self-contained and a real object. So far, it is mostly an excerpt + * of the "old" message code without any modifications. However, it + * helps to have things at the right place one we go to the meat of it. + * + * Copyright 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 <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#define SYSLOG_NAMES +#include <sys/syslog.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include "rsyslog.h" +#include "syslogd.h" +#include "template.h" +#include "srUtils.h" +#include "msg.h" + +/* rgerhards 2004-11-09: helper routines for handling the + * message object. We do only the most important things. It + * is our firm hope that this will sooner or later be + * obsoleted by liblogging. + */ + + +/* "Constructor" for a msg "object". Returns a pointer to + * the new object or NULL if no such object could be allocated. + * An object constructed via this function should only be destroyed + * via "MsgDestruct()". + */ +msg_t* MsgConstruct(void) +{ + msg_t *pM; + + if((pM = calloc(1, sizeof(msg_t))) != NULL) + { /* initialize members that are non-zero */ + pM->iRefCount = 1; + pM->iSyslogVers = -1; + pM->iSeverity = -1; + pM->iFacility = -1; + getCurrTime(&(pM->tRcvdAt)); + } + + /* DEV debugging only! dprintf("MsgConstruct\t0x%x, ref 1\n", (int)pM);*/ + + return(pM); +} + + +/* Destructor for a msg "object". Must be called to dispose + * of a msg object. + */ +void MsgDestruct(msg_t * pM) +{ + assert(pM != NULL); + /* DEV Debugging only ! dprintf("MsgDestruct\t0x%x, Ref now: %d\n", (int)pM, pM->iRefCount - 1); */ + if(--pM->iRefCount == 0) + { + /* DEV Debugging Only! dprintf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); */ + if(pM->pszUxTradMsg != NULL) + free(pM->pszUxTradMsg); + if(pM->pszRawMsg != NULL) + free(pM->pszRawMsg); + if(pM->pszTAG != NULL) + free(pM->pszTAG); + if(pM->pszHOSTNAME != NULL) + free(pM->pszHOSTNAME); + if(pM->pszRcvFrom != NULL) + free(pM->pszRcvFrom); + if(pM->pszMSG != NULL) + free(pM->pszMSG); + if(pM->pszFacility != NULL) + free(pM->pszFacility); + if(pM->pszFacilityStr != NULL) + free(pM->pszFacilityStr); + if(pM->pszSeverity != NULL) + free(pM->pszSeverity); + if(pM->pszSeverityStr != NULL) + free(pM->pszSeverityStr); + if(pM->pszRcvdAt3164 != NULL) + free(pM->pszRcvdAt3164); + if(pM->pszRcvdAt3339 != NULL) + free(pM->pszRcvdAt3339); + if(pM->pszRcvdAt_MySQL != NULL) + free(pM->pszRcvdAt_MySQL); + if(pM->pszTIMESTAMP3164 != NULL) + free(pM->pszTIMESTAMP3164); + if(pM->pszTIMESTAMP3339 != NULL) + free(pM->pszTIMESTAMP3339); + if(pM->pszTIMESTAMP_MySQL != NULL) + free(pM->pszTIMESTAMP_MySQL); + if(pM->pszPRI != NULL) + free(pM->pszPRI); + free(pM); + } +} + + +/* The macros below are used in MsgDup(). I use macros + * to keep the fuction code somewhat more readyble. It is my + * replacement for inline functions in CPP + */ +#define tmpCOPYSZ(name) \ + if(pOld->psz##name != NULL) { \ + if((pNew->psz##name = srUtilStrDup(pOld->psz##name, pOld->iLen##name)) == NULL) {\ + MsgDestruct(pNew);\ + return NULL;\ + }\ + pNew->iLen##name = pOld->iLen##name;\ + } + +/* copy the CStr objects. + * if the old value is NULL, we do not need to do anything because we + * initialized the new value to NULL via calloc(). + */ +#define tmpCOPYCSTR(name) \ + if(pOld->pCS##name != NULL) {\ + if(rsCStrConstructFromCStr(&(pNew->pCS##name), pOld->pCS##name) != RS_RET_OK) {\ + MsgDestruct(pNew);\ + return NULL;\ + }\ + } +/* Constructs a message object by duplicating another one. + * Returns NULL if duplication failed. + * rgerhards, 2007-07-10 + */ +msg_t* MsgDup(msg_t* pOld) +{ + msg_t* pNew; + + assert(pOld != NULL); + + if((pNew = (msg_t*) calloc(1, sizeof(msg_t))) == NULL) { + glblHadMemShortage = 1; + return NULL; + } + + /* now copy the message properties */ + pNew->iRefCount = 1; + pNew->iSyslogVers = pOld->iSyslogVers; + pNew->bParseHOSTNAME = pOld->bParseHOSTNAME; + pNew->iSeverity = pOld->iSeverity; + pNew->iFacility = pOld->iFacility; + pNew->bParseHOSTNAME = pOld->bParseHOSTNAME; + pNew->msgFlags = pOld->msgFlags; + pNew->iProtocolVersion = pOld->iProtocolVersion; + memcpy(&pNew->tRcvdAt, &pOld->tRcvdAt, sizeof(struct syslogTime)); + memcpy(&pNew->tTIMESTAMP, &pOld->tTIMESTAMP, sizeof(struct syslogTime)); + tmpCOPYSZ(Severity); + tmpCOPYSZ(SeverityStr); + tmpCOPYSZ(Facility); + tmpCOPYSZ(FacilityStr); + tmpCOPYSZ(PRI); + tmpCOPYSZ(RawMsg); + tmpCOPYSZ(MSG); + tmpCOPYSZ(UxTradMsg); + tmpCOPYSZ(TAG); + tmpCOPYSZ(HOSTNAME); + tmpCOPYSZ(RcvFrom); + + tmpCOPYCSTR(ProgName); + tmpCOPYCSTR(StrucData); + tmpCOPYCSTR(APPNAME); + tmpCOPYCSTR(PROCID); + tmpCOPYCSTR(MSGID); + + /* we do not copy all other cache properties, as we do not even know + * if they are needed once again. So we let them re-create if needed. + */ + + return pNew; +} +#undef tmpCOPYSZ +#undef tmpCOPYCSTR + + +/* Increment reference count - see description of the "msg" + * structure for details. As a convenience to developers, + * this method returns the msg pointer that is passed to it. + * It is recommended that it is called as follows: + * + * pSecondMsgPointer = MsgAddRef(pOrgMsgPointer); + */ +msg_t *MsgAddRef(msg_t *pM) +{ + assert(pM != NULL); + pM->iRefCount++; + /* DEV debugging only! dprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount);*/ + return(pM); +} + + +/* This functions tries to aquire the PROCID from TAG. Its primary use is + * when a legacy syslog message has been received and should be forwarded as + * syslog-protocol (or the PROCID is requested for any other reason). + * In legacy syslog, the PROCID is considered to be the character sequence + * between the first [ and the first ]. This usually are digits only, but we + * do not check that. However, if there is no closing ], we do not assume we + * can obtain a PROCID. Take in mind that not every legacy syslog message + * actually has a PROCID. + * rgerhards, 2005-11-24 + */ +static rsRetVal aquirePROCIDFromTAG(msg_t *pM) +{ + register int i; + int iRet; + + assert(pM != NULL); + if(pM->pCSPROCID != NULL) + return RS_RET_OK; /* we are already done ;) */ + + if(getProtocolVersion(pM) != 0) + return RS_RET_OK; /* we can only emulate if we have legacy format */ + + /* find first '['... */ + i = 0; + while((i < pM->iLenTAG) && (pM->pszTAG[i] != '[')) + ++i; + if(!(i < pM->iLenTAG)) + return RS_RET_OK; /* no [, so can not emulate... */ + + ++i; /* skip '[' */ + + /* now obtain the PROCID string... */ + if((pM->pCSPROCID = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pM->pCSPROCID, 16); + while((i < pM->iLenTAG) && (pM->pszTAG[i] != ']')) { + if((iRet = rsCStrAppendChar(pM->pCSPROCID, pM->pszTAG[i])) != RS_RET_OK) + return iRet; + ++i; + } + + if(!(i < pM->iLenTAG)) { + /* oops... it looked like we had a PROCID, but now it has + * turned out this is not true. In this case, we need to free + * the buffer and simply return. Note that this is NOT an error + * case! + */ + rsCStrDestruct(pM->pCSPROCID); + pM->pCSPROCID = NULL; + return RS_RET_OK; + } + + /* OK, finaally we could obtain a PROCID. So let's use it ;) */ + if((iRet = rsCStrFinish(pM->pCSPROCID)) != RS_RET_OK) + return iRet; + + return RS_RET_OK; +} + + +/* Parse and set the "programname" for a given MSG object. Programname + * is a BSD concept, it is the tag without any instance-specific information. + * Precisely, the programname is terminated by either (whichever occurs first): + * - end of tag + * - nonprintable character + * - ':' + * - '[' + * - '/' + * The above definition has been taken from the FreeBSD syslogd sources. + * + * The program name is not parsed by default, because it is infrequently-used. + * If it is needed, this function should be called first. It checks if it is + * already set and extracts it, if not. + * A message object must be provided, else a crash will occur. + * rgerhards, 2005-10-19 + */ +static rsRetVal aquireProgramName(msg_t *pM) +{ + register int i; + int iRet; + + assert(pM != NULL); + if(pM->pCSProgName == NULL) { + /* ok, we do not yet have it. So let's parse the TAG + * to obtain it. + */ + if((pM->pCSProgName = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pM->pCSProgName, 33); + for( i = 0 + ; (i < pM->iLenTAG) && isprint((int) pM->pszTAG[i]) + && (pM->pszTAG[i] != '\0') && (pM->pszTAG[i] != ':') + && (pM->pszTAG[i] != '[') && (pM->pszTAG[i] != '/') + ; ++i) { + if((iRet = rsCStrAppendChar(pM->pCSProgName, pM->pszTAG[i])) != RS_RET_OK) + return iRet; + } + if((iRet = rsCStrFinish(pM->pCSProgName)) != RS_RET_OK) + return iRet; + } + return RS_RET_OK; +} + + +/* This function moves the HOSTNAME inside the message object to the + * TAG. It is a specialised function used to handle the condition when + * a message without HOSTNAME is being processed. The missing HOSTNAME + * is only detected at a later stage, during TAG processing, so that + * we already had set the HOSTNAME property and now need to move it to + * the TAG. Of course, we could do this via a couple of get/set methods, + * but it is far more efficient to do it via this specialised method. + * This is especially important as this can be a very common case, e.g. + * when BSD syslog is acting as a sender. + * rgerhards, 2005-11-10. + */ +void moveHOSTNAMEtoTAG(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pszTAG != NULL) + free(pM->pszTAG); + pM->pszTAG = pM->pszHOSTNAME; + pM->iLenTAG = pM->iLenHOSTNAME; + pM->pszHOSTNAME = NULL; + pM->iLenHOSTNAME = 0; +} + +/* Access methods - dumb & easy, not a comment for each ;) + */ +void setProtocolVersion(msg_t *pM, int iNewVersion) +{ + assert(pM != NULL); + if(iNewVersion != 0 && iNewVersion != 1) { + dprintf("Tried to set unsupported protocol version %d - changed to 0.\n", iNewVersion); + iNewVersion = 0; + } + pM->iProtocolVersion = iNewVersion; +} + +int getProtocolVersion(msg_t *pM) +{ + assert(pM != NULL); + return(pM->iProtocolVersion); +} + +/* note: string is taken from constant pool, do NOT free */ +char *getProtocolVersionString(msg_t *pM) +{ + assert(pM != NULL); + return(pM->iProtocolVersion ? "1" : "0"); +} + +int getMSGLen(msg_t *pM) +{ + return((pM == NULL) ? 0 : pM->iLenMSG); +} + + +char *getRawMsg(msg_t *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszRawMsg == NULL) + return ""; + else + return (char*)pM->pszRawMsg; +} + +char *getUxTradMsg(msg_t *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszUxTradMsg == NULL) + return ""; + else + return (char*)pM->pszUxTradMsg; +} + +char *getMSG(msg_t *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszMSG == NULL) + return ""; + else + return (char*)pM->pszMSG; +} + + +/* Get PRI value in text form */ +char *getPRI(msg_t *pM) +{ + if(pM == NULL) + return ""; + + if(pM->pszPRI == NULL) { + /* OK, we need to construct it... + * we use a 5 byte buffer - as of + * RFC 3164, it can't be longer. Should it + * still be, snprintf will truncate... + */ + if((pM->pszPRI = malloc(5)) == NULL) return ""; + pM->iLenPRI = snprintf((char*)pM->pszPRI, 5, "%d", + LOG_MAKEPRI(pM->iFacility, pM->iSeverity)); + } + + return (char*)pM->pszPRI; +} + + +/* Get PRI value as integer */ +int getPRIi(msg_t *pM) +{ + assert(pM != NULL); + return (pM->iFacility << 3) + (pM->iSeverity); +} + + +char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt) +{ + if(pM == NULL) + return ""; + + switch(eFmt) { + case tplFmtDefault: + if(pM->pszTIMESTAMP3164 == NULL) { + if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) return ""; + formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16); + } + return(pM->pszTIMESTAMP3164); + case tplFmtMySQLDate: + if(pM->pszTIMESTAMP_MySQL == NULL) { + if((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) return ""; + formatTimestampToMySQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_MySQL, 15); + } + return(pM->pszTIMESTAMP_MySQL); + case tplFmtRFC3164Date: + if(pM->pszTIMESTAMP3164 == NULL) { + if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) return ""; + formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16); + } + return(pM->pszTIMESTAMP3164); + case tplFmtRFC3339Date: + if(pM->pszTIMESTAMP3339 == NULL) { + if((pM->pszTIMESTAMP3339 = malloc(33)) == NULL) return ""; + formatTimestamp3339(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339, 33); + } + return(pM->pszTIMESTAMP3339); + } + return "INVALID eFmt OPTION!"; +} + +char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt) +{ + if(pM == NULL) + return ""; + + switch(eFmt) { + case tplFmtDefault: + if(pM->pszRcvdAt3164 == NULL) { + if((pM->pszRcvdAt3164 = malloc(16)) == NULL) return ""; + formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16); + } + return(pM->pszRcvdAt3164); + case tplFmtMySQLDate: + if(pM->pszRcvdAt_MySQL == NULL) { + if((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) return ""; + formatTimestampToMySQL(&pM->tRcvdAt, pM->pszRcvdAt_MySQL, 15); + } + return(pM->pszRcvdAt_MySQL); + case tplFmtRFC3164Date: + if((pM->pszRcvdAt3164 = malloc(16)) == NULL) return ""; + formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16); + return(pM->pszRcvdAt3164); + case tplFmtRFC3339Date: + if(pM->pszRcvdAt3339 == NULL) { + if((pM->pszRcvdAt3339 = malloc(33)) == NULL) return ""; + formatTimestamp3339(&pM->tRcvdAt, pM->pszRcvdAt3339, 33); + } + return(pM->pszRcvdAt3339); + } + return "INVALID eFmt OPTION!"; +} + + +char *getSeverity(msg_t *pM) +{ + if(pM == NULL) + return ""; + + if(pM->pszSeverity == NULL) { + /* we use a 2 byte buffer - can only be one digit */ + if((pM->pszSeverity = malloc(2)) == NULL) return ""; + pM->iLenSeverity = + snprintf((char*)pM->pszSeverity, 2, "%d", pM->iSeverity); + } + return((char*)pM->pszSeverity); +} + + +char *getSeverityStr(msg_t *pM) +{ + syslogCODE *c; + int val; + char *name = NULL; + + if(pM == NULL) + return ""; + + if(pM->pszSeverityStr == NULL) { + for(c = rs_prioritynames, val = pM->iSeverity; c->c_name; c++) + if(c->c_val == val) { + name = c->c_name; + break; + } + if(name == NULL) { + /* we use a 2 byte buffer - can only be one digit */ + if((pM->pszSeverityStr = malloc(2)) == NULL) return ""; + pM->iLenSeverityStr = + snprintf((char*)pM->pszSeverityStr, 2, "%d", pM->iSeverity); + } else { + if((pM->pszSeverityStr = (uchar*) strdup(name)) == NULL) return ""; + pM->iLenSeverityStr = strlen((char*)name); + } + } + return((char*)pM->pszSeverityStr); +} + +char *getFacility(msg_t *pM) +{ + if(pM == NULL) + return ""; + + if(pM->pszFacility == NULL) { + /* we use a 12 byte buffer - as of + * syslog-protocol, facility can go + * up to 2^32 -1 + */ + if((pM->pszFacility = malloc(12)) == NULL) return ""; + pM->iLenFacility = + snprintf((char*)pM->pszFacility, 12, "%d", pM->iFacility); + } + return((char*)pM->pszFacility); +} + +char *getFacilityStr(msg_t *pM) +{ + syslogCODE *c; + int val; + char *name = NULL; + + if(pM == NULL) + return ""; + + if(pM->pszFacilityStr == NULL) { + for(c = rs_facilitynames, val = pM->iFacility << 3; c->c_name; c++) + if(c->c_val == val) { + name = c->c_name; + break; + } + if(name == NULL) { + /* we use a 12 byte buffer - as of + * syslog-protocol, facility can go + * up to 2^32 -1 + */ + if((pM->pszFacilityStr = malloc(12)) == NULL) return ""; + pM->iLenFacilityStr = + snprintf((char*)pM->pszFacilityStr, 12, "%d", val >> 3); + } else { + if((pM->pszFacilityStr = (uchar*)strdup(name)) == NULL) return ""; + pM->iLenFacilityStr = strlen((char*)name); + } + } + return((char*)pM->pszFacilityStr); +} + + +/* rgerhards 2004-11-24: set APP-NAME in msg object + */ +rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME) +{ + assert(pMsg != NULL); + if(pMsg->pCSAPPNAME == NULL) { + /* we need to obtain the object first */ + if((pMsg->pCSAPPNAME = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pMsg->pCSAPPNAME, 128); + } + /* if we reach this point, we have the object */ + return rsCStrSetSzStr(pMsg->pCSAPPNAME, (uchar*) pszAPPNAME); +} + + +/* This function tries to emulate APPNAME if it is not present. Its + * main use is when we have received a log record via legacy syslog and + * now would like to send out the same one via syslog-protocol. + */ +static void tryEmulateAPPNAME(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pCSAPPNAME != NULL) + return; /* we are already done */ + + if(getProtocolVersion(pM) == 0) { + /* only then it makes sense to emulate */ + MsgSetAPPNAME(pM, getProgramName(pM)); + } +} + + +/* rgerhards, 2005-11-24 + */ +int getAPPNAMELen(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pCSAPPNAME == NULL) + tryEmulateAPPNAME(pM); + return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME); +} + + +/* rgerhards, 2005-11-24 + */ +char *getAPPNAME(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pCSAPPNAME == NULL) + tryEmulateAPPNAME(pM); + return (pM->pCSAPPNAME == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSAPPNAME); +} + + + + +/* rgerhards 2004-11-24: set PROCID in msg object + */ +rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID) +{ + assert(pMsg != NULL); + if(pMsg->pCSPROCID == NULL) { + /* we need to obtain the object first */ + if((pMsg->pCSPROCID = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pMsg->pCSPROCID, 128); + } + /* if we reach this point, we have the object */ + return rsCStrSetSzStr(pMsg->pCSPROCID, (uchar*) pszPROCID); +} + +/* rgerhards, 2005-11-24 + */ +int getPROCIDLen(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pCSPROCID == NULL) + aquirePROCIDFromTAG(pM); + return (pM->pCSPROCID == NULL) ? 1 : rsCStrLen(pM->pCSPROCID); +} + + +/* rgerhards, 2005-11-24 + */ +char *getPROCID(msg_t *pM) +{ + assert(pM != NULL); + if(pM->pCSPROCID == NULL) + aquirePROCIDFromTAG(pM); + return (pM->pCSPROCID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSPROCID); +} + + +/* rgerhards 2004-11-24: set MSGID in msg object + */ +rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID) +{ + assert(pMsg != NULL); + if(pMsg->pCSMSGID == NULL) { + /* we need to obtain the object first */ + if((pMsg->pCSMSGID = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pMsg->pCSMSGID, 128); + } + /* if we reach this point, we have the object */ + return rsCStrSetSzStr(pMsg->pCSMSGID, (uchar*) pszMSGID); +} + +/* rgerhards, 2005-11-24 + */ +#if 0 /* This method is currently not called, be we like to preserve it */ +static int getMSGIDLen(msg_t *pM) +{ + return (pM->pCSMSGID == NULL) ? 1 : rsCStrLen(pM->pCSMSGID); +} +#endif + + +/* rgerhards, 2005-11-24 + */ +char *getMSGID(msg_t *pM) +{ + return (pM->pCSMSGID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSMSGID); +} + + +/* Set the TAG to a caller-provided string. This is thought + * to be a heap buffer that the caller will no longer use. This + * function is a performance optimization over MsgSetTAG(). + * rgerhards 2004-11-19 + */ +void MsgAssignTAG(msg_t *pMsg, char *pBuf) +{ + assert(pMsg != NULL); + pMsg->iLenTAG = (pBuf == NULL) ? 0 : strlen(pBuf); + pMsg->pszTAG = (uchar*) pBuf; +} + + +/* rgerhards 2004-11-16: set TAG in msg object + */ +void MsgSetTAG(msg_t *pMsg, char* pszTAG) +{ + assert(pMsg != NULL); + if(pMsg->pszTAG != NULL) + free(pMsg->pszTAG); + pMsg->iLenTAG = strlen(pszTAG); + if((pMsg->pszTAG = malloc(pMsg->iLenTAG + 1)) != NULL) + memcpy(pMsg->pszTAG, pszTAG, pMsg->iLenTAG + 1); + else + dprintf("Could not allocate memory in MsgSetTAG()\n"); +} + + +/* This function tries to emulate the TAG if none is + * set. Its primary purpose is to provide an old-style TAG + * when a syslog-protocol message has been received. Then, + * the tag is APP-NAME "[" PROCID "]". The function first checks + * if there is a TAG and, if not, if it can emulate it. + * rgerhards, 2005-11-24 + */ +static void tryEmulateTAG(msg_t *pM) +{ + int iTAGLen; + char *pBuf; + assert(pM != NULL); + + if(pM->pszTAG != NULL) + return; /* done, no need to emulate */ + + if(getProtocolVersion(pM) == 1) { + if(!strcmp(getPROCID(pM), "-")) { + /* no process ID, use APP-NAME only */ + MsgSetTAG(pM, getAPPNAME(pM)); + } else { + /* now we can try to emulate */ + iTAGLen = getAPPNAMELen(pM) + getPROCIDLen(pM) + 3; + if((pBuf = malloc(iTAGLen * sizeof(char))) == NULL) + return; /* nothing we can do */ + snprintf(pBuf, iTAGLen, "%s[%s]", getAPPNAME(pM), getPROCID(pM)); + MsgAssignTAG(pM, pBuf); + } + } +} + + +#if 0 /* This method is currently not called, be we like to preserve it */ +static int getTAGLen(msg_t *pM) +{ + if(pM == NULL) + return 0; + else { + tryEmulateTAG(pM); + if(pM->pszTAG == NULL) + return 0; + else + return pM->iLenTAG; + } +} +#endif + + +char *getTAG(msg_t *pM) +{ + if(pM == NULL) + return ""; + else { + tryEmulateTAG(pM); + if(pM->pszTAG == NULL) + return ""; + else + return (char*) pM->pszTAG; + } +} + + +int getHOSTNAMELen(msg_t *pM) +{ + if(pM == NULL) + return 0; + else + if(pM->pszHOSTNAME == NULL) + return 0; + else + return pM->iLenHOSTNAME; +} + + +char *getHOSTNAME(msg_t *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszHOSTNAME == NULL) + return ""; + else + return (char*) pM->pszHOSTNAME; +} + + +char *getRcvFrom(msg_t *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszRcvFrom == NULL) + return ""; + else + return (char*) pM->pszRcvFrom; +} +/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object + */ +rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData) +{ + assert(pMsg != NULL); + if(pMsg->pCSStrucData == NULL) { + /* we need to obtain the object first */ + if((pMsg->pCSStrucData = rsCStrConstruct()) == NULL) + return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ + rsCStrSetAllocIncrement(pMsg->pCSStrucData, 128); + } + /* if we reach this point, we have the object */ + return rsCStrSetSzStr(pMsg->pCSStrucData, (uchar*) pszStrucData); +} + +/* get the length of the "STRUCTURED-DATA" sz string + * rgerhards, 2005-11-24 + */ +#if 0 /* This method is currently not called, be we like to preserve it */ +static int getStructuredDataLen(msg_t *pM) +{ + return (pM->pCSStrucData == NULL) ? 1 : rsCStrLen(pM->pCSStrucData); +} +#endif + + +/* get the "STRUCTURED-DATA" as sz string + * rgerhards, 2005-11-24 + */ +char *getStructuredData(msg_t *pM) +{ + return (pM->pCSStrucData == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSStrucData); +} + + + +/* get the length of the "programname" sz string + * rgerhards, 2005-10-19 + */ +int getProgramNameLen(msg_t *pM) +{ + int iRet; + + assert(pM != NULL); + if((iRet = aquireProgramName(pM)) != RS_RET_OK) { + dprintf("error %d returned by aquireProgramName() in getProgramNameLen()\n", iRet); + return 0; /* best we can do (consistent wiht what getProgramName() returns) */ + } + + return (pM->pCSProgName == NULL) ? 0 : rsCStrLen(pM->pCSProgName); +} + + +/* get the "programname" as sz string + * rgerhards, 2005-10-19 + */ +char *getProgramName(msg_t *pM) +{ + int iRet; + + assert(pM != NULL); + if((iRet = aquireProgramName(pM)) != RS_RET_OK) { + dprintf("error %d returned by aquireProgramName() in getProgramName()\n", iRet); + return ""; /* best we can do */ + } + + return (pM->pCSProgName == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSProgName); +} + + +/* rgerhards 2004-11-16: set pszRcvFrom in msg object + */ +void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom) +{ + assert(pMsg != NULL); + if(pMsg->pszRcvFrom != NULL) + free(pMsg->pszRcvFrom); + + pMsg->iLenRcvFrom = strlen(pszRcvFrom); + if((pMsg->pszRcvFrom = malloc(pMsg->iLenRcvFrom + 1)) != NULL) { + memcpy(pMsg->pszRcvFrom, pszRcvFrom, pMsg->iLenRcvFrom + 1); + } +} + + +/* Set the HOSTNAME to a caller-provided string. This is thought + * to be a heap buffer that the caller will no longer use. This + * function is a performance optimization over MsgSetHOSTNAME(). + * rgerhards 2004-11-19 + */ +void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf) +{ + assert(pMsg != NULL); + assert(pBuf != NULL); + pMsg->iLenHOSTNAME = strlen(pBuf); + pMsg->pszHOSTNAME = (uchar*) pBuf; +} + + +/* rgerhards 2004-11-09: set HOSTNAME in msg object + * rgerhards, 2007-06-21: + * Does not return anything. If an error occurs, the hostname is + * simply not set. I have changed this behaviour. The only problem + * we can run into is memory shortage. If we have such, it is better + * to loose the hostname than the full message. So we silently ignore + * that problem and hope that memory will be available the next time + * we need it. The rest of the code already knows how to handle an + * unset HOSTNAME. + */ +void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME) +{ + assert(pMsg != NULL); + if(pMsg->pszHOSTNAME != NULL) + free(pMsg->pszHOSTNAME); + + pMsg->iLenHOSTNAME = strlen(pszHOSTNAME); + if((pMsg->pszHOSTNAME = malloc(pMsg->iLenHOSTNAME + 1)) != NULL) + memcpy(pMsg->pszHOSTNAME, pszHOSTNAME, pMsg->iLenHOSTNAME + 1); + else + dprintf("Could not allocate memory in MsgSetHOSTNAME()\n"); +} + + +/* Set the UxTradMsg to a caller-provided string. This is thought + * to be a heap buffer that the caller will no longer use. This + * function is a performance optimization over MsgSetUxTradMsg(). + * rgerhards 2004-11-19 + */ +#if 0 /* This method is currently not called, be we like to preserve it */ +static void MsgAssignUxTradMsg(msg_t *pMsg, char *pBuf) +{ + assert(pMsg != NULL); + assert(pBuf != NULL); + pMsg->iLenUxTradMsg = strlen(pBuf); + pMsg->pszUxTradMsg = pBuf; +} +#endif + + +/* rgerhards 2004-11-17: set the traditional Unix message in msg object + */ +int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg) +{ + assert(pMsg != NULL); + assert(pszUxTradMsg != NULL); + pMsg->iLenUxTradMsg = strlen(pszUxTradMsg); + if(pMsg->pszUxTradMsg != NULL) + free(pMsg->pszUxTradMsg); + if((pMsg->pszUxTradMsg = malloc(pMsg->iLenUxTradMsg + 1)) != NULL) + memcpy(pMsg->pszUxTradMsg, pszUxTradMsg, pMsg->iLenUxTradMsg + 1); + else + dprintf("Could not allocate memory for pszUxTradMsg buffer."); + + return(0); +} + + +/* rgerhards 2004-11-09: set MSG in msg object + */ +void MsgSetMSG(msg_t *pMsg, char* pszMSG) +{ + assert(pMsg != NULL); + assert(pszMSG != NULL); + + if(pMsg->pszMSG != NULL) + free(pMsg->pszMSG); + + pMsg->iLenMSG = strlen(pszMSG); + if((pMsg->pszMSG = malloc(pMsg->iLenMSG + 1)) != NULL) + memcpy(pMsg->pszMSG, pszMSG, pMsg->iLenMSG + 1); + else + dprintf("MsgSetMSG could not allocate memory for pszMSG buffer."); +} + +/* rgerhards 2004-11-11: set RawMsg in msg object + */ +void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg) +{ + assert(pMsg != NULL); + if(pMsg->pszRawMsg != NULL) + free(pMsg->pszRawMsg); + + pMsg->iLenRawMsg = strlen(pszRawMsg); + if((pMsg->pszRawMsg = malloc(pMsg->iLenRawMsg + 1)) != NULL) + memcpy(pMsg->pszRawMsg, pszRawMsg, pMsg->iLenRawMsg + 1); + else + dprintf("Could not allocate memory for pszRawMsg buffer."); +} + + + + +/* + * vi:set ai: + */ @@ -0,0 +1,150 @@ +/* msg.h + * Header file for all msg-related functions. + * + * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) + * + * Copyright 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. + */ +#ifndef MSG_H_INCLUDED +#define MSG_H_INCLUDED 1 + +/* rgerhards 2004-11-08: The following structure represents a + * syslog message. + * + * Important Note: + * The message object is used for multiple purposes (once it + * has been created). Once created, it actully is a read-only + * object (though we do not specifically express this). In order + * to avoid multiple copies of the same object, we use a + * reference counter. This counter is set to 1 by the constructer + * and increased by 1 with a call to MsgAddRef(). The destructor + * checks the reference count. If it is more than 1, only the counter + * will be decremented. If it is 1, however, the object is actually + * destroyed. To make this work, it is vital that MsgAddRef() is + * called each time a "copy" is stored somewhere. + */ +struct msg { + int iRefCount; /* reference counter (0 = unused) */ + short iSyslogVers; /* version of syslog protocol + * 0 - RFC 3164 + * 1 - RFC draft-protocol-08 */ + short bParseHOSTNAME; /* should the hostname be parsed from the message? */ + /* background: the hostname is not present on "regular" messages + * received via UNIX domain sockets from the same machine. However, + * it is available when we have a forwarder (e.g. rfc3195d) using local + * sockets. All in all, the parser would need parse templates, that would + * resolve all these issues... rgerhards, 2005-10-06 + */ + short iSeverity; /* the severity 0..7 */ + uchar *pszSeverity; /* severity as string... */ + int iLenSeverity; /* ... and its length. */ + uchar *pszSeverityStr; /* severity name... */ + int iLenSeverityStr; /* ... and its length. */ + int iFacility; /* Facility code (up to 2^32-1) */ + uchar *pszFacility; /* Facility as string... */ + int iLenFacility; /* ... and its length. */ + uchar *pszFacilityStr; /* facility name... */ + int iLenFacilityStr; /* ... and its length. */ + uchar *pszPRI; /* the PRI as a string */ + int iLenPRI; /* and its length */ + uchar *pszRawMsg; /* message as it was received on the + * wire. This is important in case we + * need to preserve cryptographic verifiers. + */ + int iLenRawMsg; /* length of raw message */ + uchar *pszMSG; /* the MSG part itself */ + int iLenMSG; /* Length of the MSG part */ + uchar *pszUxTradMsg; /* the traditional UNIX message */ + int iLenUxTradMsg;/* Length of the traditional UNIX message */ + uchar *pszTAG; /* pointer to tag value */ + int iLenTAG; /* Length of the TAG part */ + uchar *pszHOSTNAME; /* HOSTNAME from syslog message */ + int iLenHOSTNAME; /* Length of HOSTNAME */ + uchar *pszRcvFrom; /* System message was received from */ + int iLenRcvFrom; /* Length of pszRcvFrom */ + int iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */ + rsCStrObj *pCSProgName; /* the (BSD) program name */ + rsCStrObj *pCSStrucData;/* STRUCTURED-DATA */ + rsCStrObj *pCSAPPNAME; /* APP-NAME */ + rsCStrObj *pCSPROCID; /* PROCID */ + rsCStrObj *pCSMSGID; /* MSGID */ + struct syslogTime tRcvdAt;/* time the message entered this program */ + char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */ + char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */ + char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */ + struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */ + char *pszTIMESTAMP3164; /* TIMESTAMP as RFC3164 formatted string (always 15 charcters) */ + char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 charcters at most) */ + char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 charcters) */ + int msgFlags; /* flags associated with this message */ +}; +typedef struct msg msg_t; /* new name */ + +/* function prototypes + */ +char* getProgramName(msg_t*); +msg_t* MsgConstruct(void); +void MsgDestruct(msg_t * pM); +msg_t* MsgDup(msg_t* pOld); +msg_t *MsgAddRef(msg_t *pM); +void setProtocolVersion(msg_t *pM, int iNewVersion); +int getProtocolVersion(msg_t *pM); +char *getProtocolVersionString(msg_t *pM); +int getMSGLen(msg_t *pM); +char *getRawMsg(msg_t *pM); +char *getUxTradMsg(msg_t *pM); +char *getMSG(msg_t *pM); +char *getPRI(msg_t *pM); +int getPRIi(msg_t *pM); +char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt); +char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt); +char *getSeverity(msg_t *pM); +char *getSeverityStr(msg_t *pM); +char *getFacility(msg_t *pM); +char *getFacilityStr(msg_t *pM); +rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME); +int getAPPNAMELen(msg_t *pM); +char *getAPPNAME(msg_t *pM); +rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID); +int getPROCIDLen(msg_t *pM); +char *getPROCID(msg_t *pM); +rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID); +void MsgAssignTAG(msg_t *pMsg, char *pBuf); +void MsgSetTAG(msg_t *pMsg, char* pszTAG); +char *getTAG(msg_t *pM); +int getHOSTNAMELen(msg_t *pM); +char *getHOSTNAME(msg_t *pM); +char *getRcvFrom(msg_t *pM); +rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData); +char *getStructuredData(msg_t *pM); +int getProgramNameLen(msg_t *pM); +char *getProgramName(msg_t *pM); +void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom); +void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf); +void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME); +int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg); +void MsgSetMSG(msg_t *pMsg, char* pszMSG); +void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg); +void moveHOSTNAMEtoTAG(msg_t *pM); +char *getMSGID(msg_t *pM); + +#endif /* #ifndef MSG_H_INCLUDED */ +/* + * vi:set ai: + */ diff --git a/syslogd-types.h b/syslogd-types.h index f15acfee..3428db2a 100644 --- a/syslogd-types.h +++ b/syslogd-types.h @@ -27,6 +27,8 @@ #include "config.h" /* make sure we have autoconf macros */ #include "stringbuf.h" +#include <sys/param.h> +#include <sys/syslog.h> #ifdef UT_NAMESIZE # define UNAMESZ UT_NAMESIZE /* length of a login name */ @@ -37,6 +39,13 @@ #define MAXFNAME 200 /* max file pathname length */ +/* we define our own facility and severities */ +/* facility and severity codes */ +typedef struct _syslogCode { + char *c_name; + int c_val; +} syslogCODE; + typedef enum _TCPFRAMINGMODE { TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */ TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */ @@ -82,78 +91,6 @@ struct syslogTime { */ }; -/* rgerhards 2004-11-08: The following structure represents a - * syslog message. - * - * Important Note: - * The message object is used for multiple purposes (once it - * has been created). Once created, it actully is a read-only - * object (though we do not specifically express this). In order - * to avoid multiple copies of the same object, we use a - * reference counter. This counter is set to 1 by the constructer - * and increased by 1 with a call to MsgAddRef(). The destructor - * checks the reference count. If it is more than 1, only the counter - * will be decremented. If it is 1, however, the object is actually - * destroyed. To make this work, it is vital that MsgAddRef() is - * called each time a "copy" is stored somewhere. - */ -struct msg { - int iRefCount; /* reference counter (0 = unused) */ - short iSyslogVers; /* version of syslog protocol - * 0 - RFC 3164 - * 1 - RFC draft-protocol-08 */ - short bParseHOSTNAME; /* should the hostname be parsed from the message? */ - /* background: the hostname is not present on "regular" messages - * received via UNIX domain sockets from the same machine. However, - * it is available when we have a forwarder (e.g. rfc3195d) using local - * sockets. All in all, the parser would need parse templates, that would - * resolve all these issues... rgerhards, 2005-10-06 - */ - short iSeverity; /* the severity 0..7 */ - uchar *pszSeverity; /* severity as string... */ - int iLenSeverity; /* ... and its length. */ - uchar *pszSeverityStr; /* severity name... */ - int iLenSeverityStr; /* ... and its length. */ - int iFacility; /* Facility code (up to 2^32-1) */ - uchar *pszFacility; /* Facility as string... */ - int iLenFacility; /* ... and its length. */ - uchar *pszFacilityStr; /* facility name... */ - int iLenFacilityStr; /* ... and its length. */ - uchar *pszPRI; /* the PRI as a string */ - int iLenPRI; /* and its length */ - uchar *pszRawMsg; /* message as it was received on the - * wire. This is important in case we - * need to preserve cryptographic verifiers. - */ - int iLenRawMsg; /* length of raw message */ - uchar *pszMSG; /* the MSG part itself */ - int iLenMSG; /* Length of the MSG part */ - uchar *pszUxTradMsg; /* the traditional UNIX message */ - int iLenUxTradMsg;/* Length of the traditional UNIX message */ - uchar *pszTAG; /* pointer to tag value */ - int iLenTAG; /* Length of the TAG part */ - uchar *pszHOSTNAME; /* HOSTNAME from syslog message */ - int iLenHOSTNAME; /* Length of HOSTNAME */ - uchar *pszRcvFrom; /* System message was received from */ - int iLenRcvFrom; /* Length of pszRcvFrom */ - int iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */ - rsCStrObj *pCSProgName; /* the (BSD) program name */ - rsCStrObj *pCSStrucData;/* STRUCTURED-DATA */ - rsCStrObj *pCSAPPNAME; /* APP-NAME */ - rsCStrObj *pCSPROCID; /* PROCID */ - rsCStrObj *pCSMSGID; /* MSGID */ - struct syslogTime tRcvdAt;/* time the message entered this program */ - char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */ - char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */ - char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */ - struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */ - char *pszTIMESTAMP3164; /* TIMESTAMP as RFC3164 formatted string (always 15 charcters) */ - char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 charcters at most) */ - char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 charcters) */ - int msgFlags; /* flags associated with this message */ -}; -typedef struct msg msg_t; /* new name */ - /* values for f_type in struct filed below*/ #define F_UNUSED 0 /* unused entry */ @@ -156,7 +156,6 @@ #include <pwd.h> #include <grp.h> -#define SYSLOG_NAMES #include <sys/syslog.h> #include <sys/param.h> #ifdef __sun @@ -201,6 +200,10 @@ #include "mysql/errmsg.h" #endif +#ifdef USE_PTHREADS +#include <pthread.h> +#endif + #if HAVE_PATHS_H #include <paths.h> #endif @@ -227,23 +230,34 @@ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) #endif +#include "rsyslog.h" +#include "template.h" +#include "outchannel.h" +#include "syslogd.h" + +#include "stringbuf.h" +#include "parse.h" +#include "srUtils.h" +#include "msg.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 +# 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) -typedef struct _code { - char *c_name; - int c_val; -} CODE; - -CODE prioritynames[] = + +syslogCODE rs_prioritynames[] = { { "alert", LOG_ALERT }, { "crit", LOG_CRIT }, @@ -260,7 +274,7 @@ CODE prioritynames[] = { NULL, -1 } }; -CODE facilitynames[] = +syslogCODE rs_facilitynames[] = { { "auth", LOG_AUTH }, { "authpriv", LOG_AUTHPRIV }, @@ -286,22 +300,6 @@ CODE facilitynames[] = { "local7", LOG_LOCAL7 }, { NULL, -1 } }; -#endif - -#include "rsyslog.h" -#include "template.h" -#include "outchannel.h" -#include "syslogd.h" -#include "syslogd-types.h" - - -#include "stringbuf.h" -#include "parse.h" -#include "srUtils.h" - -#ifdef USE_PTHREADS -#include <pthread.h> -#endif #ifdef WITH_DB #define _DB_MAXDBLEN 128 /* maximum number of db */ @@ -443,7 +441,7 @@ static int restart = 0; /* do restart (config read) - multithread safe */ static int bRequestDoMark = 0; /* do mark processing? (multithread safe) */ #define MAXFUNIX 20 -static int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */ +int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */ static int iDynaFileCacheSize = 10; /* max cache for dynamic files */ static int fCreateMode = 0644; /* mode to use when creating files */ static int fDirCreateMode = 0644; /* mode to use when creating files */ @@ -775,8 +773,6 @@ static msgQueue *queueInit (void); static void *singleWorker(); /* REMOVEME later 2005-10-24 */ #endif /* Function prototypes. */ -static rsRetVal aquirePROCIDFromTAG(msg_t *pM); -static char* getProgramName(msg_t*); static char **crunch_list(char *list); static void printchopped(char *hname, char *msg, int len, int fd, int iSourceType); static void printline(char *hname, char *msg, int iSource); @@ -800,7 +796,6 @@ static void DBErrorHandler(register selector_t *f); #endif static int getSubString(uchar **pSrc, char *pDst, size_t DstSize, char cSep); -static void getCurrTime(struct syslogTime *t); static void cflineSetTemplateAndIOV(selector_t *f, char *pTemplateName); /* Access functions for the selector_t. These functions are primarily @@ -2591,7 +2586,7 @@ static int srSLMGParseTIMESTAMP3164(struct syslogTime *pTime, char* pszTS) * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occured. */ -static int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst) +int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst) { /* currently we do not consider localtime/utc. This may later be * added. If so, I recommend using a property replacer option @@ -2619,7 +2614,7 @@ static int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLen * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occured. */ -static int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf) +int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf) { int iRet; char szTZ[7]; /* buffer for TZ information */ @@ -2670,7 +2665,7 @@ static int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf * returns the size of the timestamp written in bytes (without * the string termnator). If 0 is returend, an error occured. */ -static int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf) +int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf) { static char* monthNames[13] = {"ERR", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", @@ -2723,7 +2718,7 @@ static int formatTimestamp(struct syslogTime *ts, char* pBuf, size_t iLenBuf) * * Obviously, all caller-provided pointers must not be NULL... */ -static void getCurrTime(struct syslogTime *t) +void getCurrTime(struct syslogTime *t) { struct timeval tp; struct tm *tm; @@ -2771,13 +2766,13 @@ static void getCurrTime(struct syslogTime *t) */ char *textpri(char *pRes, size_t pResLen, int pri) { - CODE *c_pri, *c_fac; + syslogCODE *c_pri, *c_fac; assert(pRes != NULL); assert(pResLen > 0); - for (c_fac = facilitynames; c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri)<<3); c_fac++); - for (c_pri = prioritynames; c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++); + for (c_fac = rs_facilitynames; c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri)<<3); c_fac++); + for (c_pri = rs_prioritynames; c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++); snprintf (pRes, pResLen, "%s.%s<%d>", c_fac->c_name, c_pri->c_name, pri); @@ -2785,998 +2780,6 @@ char *textpri(char *pRes, size_t pResLen, int pri) } -/* rgerhards 2004-11-09: helper routines for handling the - * message object. We do only the most important things. It - * is our firm hope that this will sooner or later be - * obsoleted by liblogging. - */ - - -/* "Constructor" for a msg "object". Returns a pointer to - * the new object or NULL if no such object could be allocated. - * An object constructed via this function should only be destroyed - * via "MsgDestruct()". - */ -static msg_t* MsgConstruct() -{ - msg_t *pM; - - if((pM = calloc(1, sizeof(msg_t))) != NULL) - { /* initialize members that are non-zero */ - pM->iRefCount = 1; - pM->iSyslogVers = -1; - pM->iSeverity = -1; - pM->iFacility = -1; - getCurrTime(&(pM->tRcvdAt)); - } - - /* DEV debugging only! dprintf("MsgConstruct\t0x%x, ref 1\n", (int)pM);*/ - - return(pM); -} - - -/* Destructor for a msg "object". Must be called to dispose - * of a msg object. - */ -static void MsgDestruct(msg_t * pM) -{ - assert(pM != NULL); - /* DEV Debugging only ! dprintf("MsgDestruct\t0x%x, Ref now: %d\n", (int)pM, pM->iRefCount - 1); */ - if(--pM->iRefCount == 0) - { - /* DEV Debugging Only! dprintf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); */ - if(pM->pszUxTradMsg != NULL) - free(pM->pszUxTradMsg); - if(pM->pszRawMsg != NULL) - free(pM->pszRawMsg); - if(pM->pszTAG != NULL) - free(pM->pszTAG); - if(pM->pszHOSTNAME != NULL) - free(pM->pszHOSTNAME); - if(pM->pszRcvFrom != NULL) - free(pM->pszRcvFrom); - if(pM->pszMSG != NULL) - free(pM->pszMSG); - if(pM->pszFacility != NULL) - free(pM->pszFacility); - if(pM->pszFacilityStr != NULL) - free(pM->pszFacilityStr); - if(pM->pszSeverity != NULL) - free(pM->pszSeverity); - if(pM->pszSeverityStr != NULL) - free(pM->pszSeverityStr); - if(pM->pszRcvdAt3164 != NULL) - free(pM->pszRcvdAt3164); - if(pM->pszRcvdAt3339 != NULL) - free(pM->pszRcvdAt3339); - if(pM->pszRcvdAt_MySQL != NULL) - free(pM->pszRcvdAt_MySQL); - if(pM->pszTIMESTAMP3164 != NULL) - free(pM->pszTIMESTAMP3164); - if(pM->pszTIMESTAMP3339 != NULL) - free(pM->pszTIMESTAMP3339); - if(pM->pszTIMESTAMP_MySQL != NULL) - free(pM->pszTIMESTAMP_MySQL); - if(pM->pszPRI != NULL) - free(pM->pszPRI); - free(pM); - } -} - - -/* The macros below are used in MsgDup(). I use macros - * to keep the fuction code somewhat more readyble. It is my - * replacement for inline functions in CPP - */ -#define tmpCOPYSZ(name) \ - if(pOld->psz##name != NULL) { \ - if((pNew->psz##name = srUtilStrDup(pOld->psz##name, pOld->iLen##name)) == NULL) {\ - MsgDestruct(pNew);\ - return NULL;\ - }\ - pNew->iLen##name = pOld->iLen##name;\ - } - -/* copy the CStr objects. - * if the old value is NULL, we do not need to do anything because we - * initialized the new value to NULL via calloc(). - */ -#define tmpCOPYCSTR(name) \ - if(pOld->pCS##name != NULL) {\ - if(rsCStrConstructFromCStr(&(pNew->pCS##name), pOld->pCS##name) != RS_RET_OK) {\ - MsgDestruct(pNew);\ - return NULL;\ - }\ - } -/* Constructs a message object by duplicating another one. - * Returns NULL if duplication failed. - * rgerhards, 2007-07-10 - */ -static msg_t* MsgDup(msg_t* pOld) -{ - msg_t* pNew; - - assert(pOld != NULL); - - if((pNew = (msg_t*) calloc(1, sizeof(msg_t))) == NULL) { - glblHadMemShortage = 1; - return NULL; - } - - /* now copy the message properties */ - pNew->iRefCount = 1; - pNew->iSyslogVers = pOld->iSyslogVers; - pNew->bParseHOSTNAME = pOld->bParseHOSTNAME; - pNew->iSeverity = pOld->iSeverity; - pNew->iFacility = pOld->iFacility; - pNew->bParseHOSTNAME = pOld->bParseHOSTNAME; - pNew->msgFlags = pOld->msgFlags; - pNew->iProtocolVersion = pOld->iProtocolVersion; - memcpy(&pNew->tRcvdAt, &pOld->tRcvdAt, sizeof(struct syslogTime)); - memcpy(&pNew->tTIMESTAMP, &pOld->tTIMESTAMP, sizeof(struct syslogTime)); - tmpCOPYSZ(Severity); - tmpCOPYSZ(SeverityStr); - tmpCOPYSZ(Facility); - tmpCOPYSZ(FacilityStr); - tmpCOPYSZ(PRI); - tmpCOPYSZ(RawMsg); - tmpCOPYSZ(MSG); - tmpCOPYSZ(UxTradMsg); - tmpCOPYSZ(TAG); - tmpCOPYSZ(HOSTNAME); - tmpCOPYSZ(RcvFrom); - - tmpCOPYCSTR(ProgName); - tmpCOPYCSTR(StrucData); - tmpCOPYCSTR(APPNAME); - tmpCOPYCSTR(PROCID); - tmpCOPYCSTR(MSGID); - - /* we do not copy all other cache properties, as we do not even know - * if they are needed once again. So we let them re-create if needed. - */ - - return pNew; -} -#undef tmpCOPYSZ -#undef tmpCOPYCSTR - - -/* Increment reference count - see description of the "msg" - * structure for details. As a convenience to developers, - * this method returns the msg pointer that is passed to it. - * It is recommended that it is called as follows: - * - * pSecondMsgPointer = MsgAddRef(pOrgMsgPointer); - */ -static msg_t *MsgAddRef(msg_t *pM) -{ - assert(pM != NULL); - pM->iRefCount++; - /* DEV debugging only! dprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount);*/ - return(pM); -} - -/* Access methods - dumb & easy, not a comment for each ;) - */ -static void setProtocolVersion(msg_t *pM, int iNewVersion) -{ - assert(pM != NULL); - if(iNewVersion != 0 && iNewVersion != 1) { - dprintf("Tried to set unsupported protocol version %d - changed to 0.\n", iNewVersion); - iNewVersion = 0; - } - pM->iProtocolVersion = iNewVersion; -} - -static int getProtocolVersion(msg_t *pM) -{ - assert(pM != NULL); - return(pM->iProtocolVersion); -} - -/* note: string is taken from constant pool, do NOT free */ -static char *getProtocolVersionString(msg_t *pM) -{ - assert(pM != NULL); - return(pM->iProtocolVersion ? "1" : "0"); -} - -static int getMSGLen(msg_t *pM) -{ - return((pM == NULL) ? 0 : pM->iLenMSG); -} - - -static char *getRawMsg(msg_t *pM) -{ - if(pM == NULL) - return ""; - else - if(pM->pszRawMsg == NULL) - return ""; - else - return (char*)pM->pszRawMsg; -} - -static char *getUxTradMsg(msg_t *pM) -{ - if(pM == NULL) - return ""; - else - if(pM->pszUxTradMsg == NULL) - return ""; - else - return (char*)pM->pszUxTradMsg; -} - -static char *getMSG(msg_t *pM) -{ - if(pM == NULL) - return ""; - else - if(pM->pszMSG == NULL) - return ""; - else - return (char*)pM->pszMSG; -} - - -/* Get PRI value in text form */ -static char *getPRI(msg_t *pM) -{ - if(pM == NULL) - return ""; - - if(pM->pszPRI == NULL) { - /* OK, we need to construct it... - * we use a 5 byte buffer - as of - * RFC 3164, it can't be longer. Should it - * still be, snprintf will truncate... - */ - if((pM->pszPRI = malloc(5)) == NULL) return ""; - pM->iLenPRI = snprintf((char*)pM->pszPRI, 5, "%d", - LOG_MAKEPRI(pM->iFacility, pM->iSeverity)); - } - - return (char*)pM->pszPRI; -} - - -/* Get PRI value as integer */ -static int getPRIi(msg_t *pM) -{ - assert(pM != NULL); - return (pM->iFacility << 3) + (pM->iSeverity); -} - - -static char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt) -{ - if(pM == NULL) - return ""; - - switch(eFmt) { - case tplFmtDefault: - if(pM->pszTIMESTAMP3164 == NULL) { - if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) return ""; - formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16); - } - return(pM->pszTIMESTAMP3164); - case tplFmtMySQLDate: - if(pM->pszTIMESTAMP_MySQL == NULL) { - if((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) return ""; - formatTimestampToMySQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_MySQL, 15); - } - return(pM->pszTIMESTAMP_MySQL); - case tplFmtRFC3164Date: - if(pM->pszTIMESTAMP3164 == NULL) { - if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) return ""; - formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16); - } - return(pM->pszTIMESTAMP3164); - case tplFmtRFC3339Date: - if(pM->pszTIMESTAMP3339 == NULL) { - if((pM->pszTIMESTAMP3339 = malloc(33)) == NULL) return ""; - formatTimestamp3339(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339, 33); - } - return(pM->pszTIMESTAMP3339); - } - return "INVALID eFmt OPTION!"; -} - -static char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt) -{ - if(pM == NULL) - return ""; - - switch(eFmt) { - case tplFmtDefault: - if(pM->pszRcvdAt3164 == NULL) { - if((pM->pszRcvdAt3164 = malloc(16)) == NULL) return ""; - formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16); - } - return(pM->pszRcvdAt3164); - case tplFmtMySQLDate: - if(pM->pszRcvdAt_MySQL == NULL) { - if((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) return ""; - formatTimestampToMySQL(&pM->tRcvdAt, pM->pszRcvdAt_MySQL, 15); - } - return(pM->pszRcvdAt_MySQL); - case tplFmtRFC3164Date: - if((pM->pszRcvdAt3164 = malloc(16)) == NULL) return ""; - formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16); - return(pM->pszRcvdAt3164); - case tplFmtRFC3339Date: - if(pM->pszRcvdAt3339 == NULL) { - if((pM->pszRcvdAt3339 = malloc(33)) == NULL) return ""; - formatTimestamp3339(&pM->tRcvdAt, pM->pszRcvdAt3339, 33); - } - return(pM->pszRcvdAt3339); - } - return "INVALID eFmt OPTION!"; -} - - -char *getSeverity(msg_t *pM) -{ - if(pM == NULL) - return ""; - - if(pM->pszSeverity == NULL) { - /* we use a 2 byte buffer - can only be one digit */ - if((pM->pszSeverity = malloc(2)) == NULL) return ""; - pM->iLenSeverity = - snprintf((char*)pM->pszSeverity, 2, "%d", pM->iSeverity); - } - return((char*)pM->pszSeverity); -} - -static char *getSeverityStr(msg_t *pM) -{ - CODE *c; - int val; - char *name = NULL; - - if(pM == NULL) - return ""; - - if(pM->pszSeverityStr == NULL) { - for(c = prioritynames, val = pM->iSeverity; c->c_name; c++) - if(c->c_val == val) { - name = c->c_name; - break; - } - if(name == NULL) { - /* we use a 2 byte buffer - can only be one digit */ - if((pM->pszSeverityStr = malloc(2)) == NULL) return ""; - pM->iLenSeverityStr = - snprintf((char*)pM->pszSeverityStr, 2, "%d", pM->iSeverity); - } else { - if((pM->pszSeverityStr = (uchar*) strdup(name)) == NULL) return ""; - pM->iLenSeverityStr = strlen((char*)name); - } - } - return((char*)pM->pszSeverityStr); -} - -static char *getFacility(msg_t *pM) -{ - if(pM == NULL) - return ""; - - if(pM->pszFacility == NULL) { - /* we use a 12 byte buffer - as of - * syslog-protocol, facility can go - * up to 2^32 -1 - */ - if((pM->pszFacility = malloc(12)) == NULL) return ""; - pM->iLenFacility = - snprintf((char*)pM->pszFacility, 12, "%d", pM->iFacility); - } - return((char*)pM->pszFacility); -} - -static char *getFacilityStr(msg_t *pM) -{ - CODE *c; - int val; - char *name = NULL; - - if(pM == NULL) - return ""; - - if(pM->pszFacilityStr == NULL) { - for(c = facilitynames, val = pM->iFacility << 3; c->c_name; c++) - if(c->c_val == val) { - name = c->c_name; - break; - } - if(name == NULL) { - /* we use a 12 byte buffer - as of - * syslog-protocol, facility can go - * up to 2^32 -1 - */ - if((pM->pszFacilityStr = malloc(12)) == NULL) return ""; - pM->iLenFacilityStr = - snprintf((char*)pM->pszFacilityStr, 12, "%d", val >> 3); - } else { - if((pM->pszFacilityStr = (uchar*)strdup(name)) == NULL) return ""; - pM->iLenFacilityStr = strlen((char*)name); - } - } - return((char*)pM->pszFacilityStr); -} - - -/* rgerhards 2004-11-24: set APP-NAME in msg object - */ -static rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME) -{ - assert(pMsg != NULL); - if(pMsg->pCSAPPNAME == NULL) { - /* we need to obtain the object first */ - if((pMsg->pCSAPPNAME = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pMsg->pCSAPPNAME, 128); - } - /* if we reach this point, we have the object */ - return rsCStrSetSzStr(pMsg->pCSAPPNAME, (uchar*) pszAPPNAME); -} - - -/* This function tries to emulate APPNAME if it is not present. Its - * main use is when we have received a log record via legacy syslog and - * now would like to send out the same one via syslog-protocol. - */ -static void tryEmulateAPPNAME(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pCSAPPNAME != NULL) - return; /* we are already done */ - - if(getProtocolVersion(pM) == 0) { - /* only then it makes sense to emulate */ - MsgSetAPPNAME(pM, getProgramName(pM)); - } -} - - -/* rgerhards, 2005-11-24 - */ -static int getAPPNAMELen(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pCSAPPNAME == NULL) - tryEmulateAPPNAME(pM); - return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME); -} - - -/* rgerhards, 2005-11-24 - */ -static char *getAPPNAME(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pCSAPPNAME == NULL) - tryEmulateAPPNAME(pM); - return (pM->pCSAPPNAME == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSAPPNAME); -} - - - - -/* rgerhards 2004-11-24: set PROCID in msg object - */ -static rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID) -{ - assert(pMsg != NULL); - if(pMsg->pCSPROCID == NULL) { - /* we need to obtain the object first */ - if((pMsg->pCSPROCID = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pMsg->pCSPROCID, 128); - } - /* if we reach this point, we have the object */ - return rsCStrSetSzStr(pMsg->pCSPROCID, (uchar*) pszPROCID); -} - -/* rgerhards, 2005-11-24 - */ -static int getPROCIDLen(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pCSPROCID == NULL) - aquirePROCIDFromTAG(pM); - return (pM->pCSPROCID == NULL) ? 1 : rsCStrLen(pM->pCSPROCID); -} - - -/* rgerhards, 2005-11-24 - */ -static char *getPROCID(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pCSPROCID == NULL) - aquirePROCIDFromTAG(pM); - return (pM->pCSPROCID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSPROCID); -} - - -/* rgerhards 2004-11-24: set MSGID in msg object - */ -static rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID) -{ - assert(pMsg != NULL); - if(pMsg->pCSMSGID == NULL) { - /* we need to obtain the object first */ - if((pMsg->pCSMSGID = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pMsg->pCSMSGID, 128); - } - /* if we reach this point, we have the object */ - return rsCStrSetSzStr(pMsg->pCSMSGID, (uchar*) pszMSGID); -} - -/* rgerhards, 2005-11-24 - */ -#if 0 /* This method is currently not called, be we like to preserve it */ -static int getMSGIDLen(msg_t *pM) -{ - return (pM->pCSMSGID == NULL) ? 1 : rsCStrLen(pM->pCSMSGID); -} -#endif - - -/* rgerhards, 2005-11-24 - */ -static char *getMSGID(msg_t *pM) -{ - return (pM->pCSMSGID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSMSGID); -} - - -/* Set the TAG to a caller-provided string. This is thought - * to be a heap buffer that the caller will no longer use. This - * function is a performance optimization over MsgSetTAG(). - * rgerhards 2004-11-19 - */ -static void MsgAssignTAG(msg_t *pMsg, char *pBuf) -{ - assert(pMsg != NULL); - pMsg->iLenTAG = (pBuf == NULL) ? 0 : strlen(pBuf); - pMsg->pszTAG = (uchar*) pBuf; -} - - -/* rgerhards 2004-11-16: set TAG in msg object - */ -static void MsgSetTAG(msg_t *pMsg, char* pszTAG) -{ - assert(pMsg != NULL); - if(pMsg->pszTAG != NULL) - free(pMsg->pszTAG); - pMsg->iLenTAG = strlen(pszTAG); - if((pMsg->pszTAG = malloc(pMsg->iLenTAG + 1)) != NULL) - memcpy(pMsg->pszTAG, pszTAG, pMsg->iLenTAG + 1); - else - dprintf("Could not allocate memory in MsgSetTAG()\n"); -} - - -/* This function tries to emulate the TAG if none is - * set. Its primary purpose is to provide an old-style TAG - * when a syslog-protocol message has been received. Then, - * the tag is APP-NAME "[" PROCID "]". The function first checks - * if there is a TAG and, if not, if it can emulate it. - * rgerhards, 2005-11-24 - */ -static void tryEmulateTAG(msg_t *pM) -{ - int iTAGLen; - char *pBuf; - assert(pM != NULL); - - if(pM->pszTAG != NULL) - return; /* done, no need to emulate */ - - if(getProtocolVersion(pM) == 1) { - if(!strcmp(getPROCID(pM), "-")) { - /* no process ID, use APP-NAME only */ - MsgSetTAG(pM, getAPPNAME(pM)); - } else { - /* now we can try to emulate */ - iTAGLen = getAPPNAMELen(pM) + getPROCIDLen(pM) + 3; - if((pBuf = malloc(iTAGLen * sizeof(char))) == NULL) - return; /* nothing we can do */ - snprintf(pBuf, iTAGLen, "%s[%s]", getAPPNAME(pM), getPROCID(pM)); - MsgAssignTAG(pM, pBuf); - } - } -} - - -#if 0 /* This method is currently not called, be we like to preserve it */ -static int getTAGLen(msg_t *pM) -{ - if(pM == NULL) - return 0; - else { - tryEmulateTAG(pM); - if(pM->pszTAG == NULL) - return 0; - else - return pM->iLenTAG; - } -} -#endif - - -static char *getTAG(msg_t *pM) -{ - if(pM == NULL) - return ""; - else { - tryEmulateTAG(pM); - if(pM->pszTAG == NULL) - return ""; - else - return (char*) pM->pszTAG; - } -} - - -static int getHOSTNAMELen(msg_t *pM) -{ - if(pM == NULL) - return 0; - else - if(pM->pszHOSTNAME == NULL) - return 0; - else - return pM->iLenHOSTNAME; -} - - -static char *getHOSTNAME(msg_t *pM) -{ - if(pM == NULL) - return ""; - else - if(pM->pszHOSTNAME == NULL) - return ""; - else - return (char*) pM->pszHOSTNAME; -} - - -static char *getRcvFrom(msg_t *pM) -{ - if(pM == NULL) - return ""; - else - if(pM->pszRcvFrom == NULL) - return ""; - else - return (char*) pM->pszRcvFrom; -} -/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object - */ -static rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData) -{ - assert(pMsg != NULL); - if(pMsg->pCSStrucData == NULL) { - /* we need to obtain the object first */ - if((pMsg->pCSStrucData = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pMsg->pCSStrucData, 128); - } - /* if we reach this point, we have the object */ - return rsCStrSetSzStr(pMsg->pCSStrucData, (uchar*) pszStrucData); -} - -/* get the length of the "STRUCTURED-DATA" sz string - * rgerhards, 2005-11-24 - */ -#if 0 /* This method is currently not called, be we like to preserve it */ -static int getStructuredDataLen(msg_t *pM) -{ - return (pM->pCSStrucData == NULL) ? 1 : rsCStrLen(pM->pCSStrucData); -} -#endif - - -/* get the "STRUCTURED-DATA" as sz string - * rgerhards, 2005-11-24 - */ -static char *getStructuredData(msg_t *pM) -{ - return (pM->pCSStrucData == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSStrucData); -} - - -/* This function moves the HOSTNAME inside the message object to the - * TAG. It is a specialised function used to handle the condition when - * a message without HOSTNAME is being processed. The missing HOSTNAME - * is only detected at a later stage, during TAG processing, so that - * we already had set the HOSTNAME property and now need to move it to - * the TAG. Of course, we could do this via a couple of get/set methods, - * but it is far more efficient to do it via this specialised method. - * This is especially important as this can be a very common case, e.g. - * when BSD syslog is acting as a sender. - * rgerhards, 2005-11-10. - */ -static void moveHOSTNAMEtoTAG(msg_t *pM) -{ - assert(pM != NULL); - if(pM->pszTAG != NULL) - free(pM->pszTAG); - pM->pszTAG = pM->pszHOSTNAME; - pM->iLenTAG = pM->iLenHOSTNAME; - pM->pszHOSTNAME = NULL; - pM->iLenHOSTNAME = 0; -} - - -/* This functions tries to aquire the PROCID from TAG. Its primary use is - * when a legacy syslog message has been received and should be forwarded as - * syslog-protocol (or the PROCID is requested for any other reason). - * In legacy syslog, the PROCID is considered to be the character sequence - * between the first [ and the first ]. This usually are digits only, but we - * do not check that. However, if there is no closing ], we do not assume we - * can obtain a PROCID. Take in mind that not every legacy syslog message - * actually has a PROCID. - * rgerhards, 2005-11-24 - */ -static rsRetVal aquirePROCIDFromTAG(msg_t *pM) -{ - register int i; - int iRet; - - assert(pM != NULL); - if(pM->pCSPROCID != NULL) - return RS_RET_OK; /* we are already done ;) */ - - if(getProtocolVersion(pM) != 0) - return RS_RET_OK; /* we can only emulate if we have legacy format */ - - /* find first '['... */ - i = 0; - while((i < pM->iLenTAG) && (pM->pszTAG[i] != '[')) - ++i; - if(!(i < pM->iLenTAG)) - return RS_RET_OK; /* no [, so can not emulate... */ - - ++i; /* skip '[' */ - - /* now obtain the PROCID string... */ - if((pM->pCSPROCID = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pM->pCSPROCID, 16); - while((i < pM->iLenTAG) && (pM->pszTAG[i] != ']')) { - if((iRet = rsCStrAppendChar(pM->pCSPROCID, pM->pszTAG[i])) != RS_RET_OK) - return iRet; - ++i; - } - - if(!(i < pM->iLenTAG)) { - /* oops... it looked like we had a PROCID, but now it has - * turned out this is not true. In this case, we need to free - * the buffer and simply return. Note that this is NOT an error - * case! - */ - rsCStrDestruct(pM->pCSPROCID); - pM->pCSPROCID = NULL; - return RS_RET_OK; - } - - /* OK, finaally we could obtain a PROCID. So let's use it ;) */ - if((iRet = rsCStrFinish(pM->pCSPROCID)) != RS_RET_OK) - return iRet; - - return RS_RET_OK; -} - - -/* Parse and set the "programname" for a given MSG object. Programname - * is a BSD concept, it is the tag without any instance-specific information. - * Precisely, the programname is terminated by either (whichever occurs first): - * - end of tag - * - nonprintable character - * - ':' - * - '[' - * - '/' - * The above definition has been taken from the FreeBSD syslogd sources. - * - * The program name is not parsed by default, because it is infrequently-used. - * If it is needed, this function should be called first. It checks if it is - * already set and extracts it, if not. - * A message object must be provided, else a crash will occur. - * rgerhards, 2005-10-19 - */ -static rsRetVal aquireProgramName(msg_t *pM) -{ - register int i; - int iRet; - - assert(pM != NULL); - if(pM->pCSProgName == NULL) { - /* ok, we do not yet have it. So let's parse the TAG - * to obtain it. - */ - if((pM->pCSProgName = rsCStrConstruct()) == NULL) - return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */ - rsCStrSetAllocIncrement(pM->pCSProgName, 33); - for( i = 0 - ; (i < pM->iLenTAG) && isprint((int) pM->pszTAG[i]) - && (pM->pszTAG[i] != '\0') && (pM->pszTAG[i] != ':') - && (pM->pszTAG[i] != '[') && (pM->pszTAG[i] != '/') - ; ++i) { - if((iRet = rsCStrAppendChar(pM->pCSProgName, pM->pszTAG[i])) != RS_RET_OK) - return iRet; - } - if((iRet = rsCStrFinish(pM->pCSProgName)) != RS_RET_OK) - return iRet; - } - return RS_RET_OK; -} - - -/* get the length of the "programname" sz string - * rgerhards, 2005-10-19 - */ -static int getProgramNameLen(msg_t *pM) -{ - int iRet; - - assert(pM != NULL); - if((iRet = aquireProgramName(pM)) != RS_RET_OK) { - dprintf("error %d returned by aquireProgramName() in getProgramNameLen()\n", iRet); - return 0; /* best we can do (consistent wiht what getProgramName() returns) */ - } - - return (pM->pCSProgName == NULL) ? 0 : rsCStrLen(pM->pCSProgName); -} - - -/* get the "programname" as sz string - * rgerhards, 2005-10-19 - */ -static char *getProgramName(msg_t *pM) -{ - int iRet; - - assert(pM != NULL); - if((iRet = aquireProgramName(pM)) != RS_RET_OK) { - dprintf("error %d returned by aquireProgramName() in getProgramName()\n", iRet); - return ""; /* best we can do */ - } - - return (pM->pCSProgName == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSProgName); -} - - -/* rgerhards 2004-11-16: set pszRcvFrom in msg object - */ -static void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom) -{ - assert(pMsg != NULL); - if(pMsg->pszRcvFrom != NULL) - free(pMsg->pszRcvFrom); - - pMsg->iLenRcvFrom = strlen(pszRcvFrom); - if((pMsg->pszRcvFrom = malloc(pMsg->iLenRcvFrom + 1)) != NULL) { - memcpy(pMsg->pszRcvFrom, pszRcvFrom, pMsg->iLenRcvFrom + 1); - } -} - - -/* Set the HOSTNAME to a caller-provided string. This is thought - * to be a heap buffer that the caller will no longer use. This - * function is a performance optimization over MsgSetHOSTNAME(). - * rgerhards 2004-11-19 - */ -static void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf) -{ - assert(pMsg != NULL); - assert(pBuf != NULL); - pMsg->iLenHOSTNAME = strlen(pBuf); - pMsg->pszHOSTNAME = (uchar*) pBuf; -} - - -/* rgerhards 2004-11-09: set HOSTNAME in msg object - * rgerhards, 2007-06-21: - * Does not return anything. If an error occurs, the hostname is - * simply not set. I have changed this behaviour. The only problem - * we can run into is memory shortage. If we have such, it is better - * to loose the hostname than the full message. So we silently ignore - * that problem and hope that memory will be available the next time - * we need it. The rest of the code already knows how to handle an - * unset HOSTNAME. - */ -static void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME) -{ - assert(pMsg != NULL); - if(pMsg->pszHOSTNAME != NULL) - free(pMsg->pszHOSTNAME); - - pMsg->iLenHOSTNAME = strlen(pszHOSTNAME); - if((pMsg->pszHOSTNAME = malloc(pMsg->iLenHOSTNAME + 1)) != NULL) - memcpy(pMsg->pszHOSTNAME, pszHOSTNAME, pMsg->iLenHOSTNAME + 1); - else - dprintf("Could not allocate memory in MsgSetHOSTNAME()\n"); -} - - -/* Set the UxTradMsg to a caller-provided string. This is thought - * to be a heap buffer that the caller will no longer use. This - * function is a performance optimization over MsgSetUxTradMsg(). - * rgerhards 2004-11-19 - */ -#if 0 /* This method is currently not called, be we like to preserve it */ -static void MsgAssignUxTradMsg(msg_t *pMsg, char *pBuf) -{ - assert(pMsg != NULL); - assert(pBuf != NULL); - pMsg->iLenUxTradMsg = strlen(pBuf); - pMsg->pszUxTradMsg = pBuf; -} -#endif - - -/* rgerhards 2004-11-17: set the traditional Unix message in msg object - */ -static int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg) -{ - assert(pMsg != NULL); - assert(pszUxTradMsg != NULL); - pMsg->iLenUxTradMsg = strlen(pszUxTradMsg); - if(pMsg->pszUxTradMsg != NULL) - free(pMsg->pszUxTradMsg); - if((pMsg->pszUxTradMsg = malloc(pMsg->iLenUxTradMsg + 1)) != NULL) - memcpy(pMsg->pszUxTradMsg, pszUxTradMsg, pMsg->iLenUxTradMsg + 1); - else - dprintf("Could not allocate memory for pszUxTradMsg buffer."); - - return(0); -} - - -/* rgerhards 2004-11-09: set MSG in msg object - */ -static void MsgSetMSG(msg_t *pMsg, char* pszMSG) -{ - assert(pMsg != NULL); - assert(pszMSG != NULL); - - if(pMsg->pszMSG != NULL) - free(pMsg->pszMSG); - - pMsg->iLenMSG = strlen(pszMSG); - if((pMsg->pszMSG = malloc(pMsg->iLenMSG + 1)) != NULL) - memcpy(pMsg->pszMSG, pszMSG, pMsg->iLenMSG + 1); - else - dprintf("MsgSetMSG could not allocate memory for pszMSG buffer."); -} - -/* rgerhards 2004-11-11: set RawMsg in msg object - */ -static void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg) -{ - assert(pMsg != NULL); - if(pMsg->pszRawMsg != NULL) - free(pMsg->pszRawMsg); - - pMsg->iLenRawMsg = strlen(pszRawMsg); - if((pMsg->pszRawMsg = malloc(pMsg->iLenRawMsg + 1)) != NULL) - memcpy(pMsg->pszRawMsg, pszRawMsg, pMsg->iLenRawMsg + 1); - else - dprintf("Could not allocate memory for pszRawMsg buffer."); -} - - /* This function returns the current date in different * variants. It is used to construct the $NOW series of * system properties. The returned buffer must be freed @@ -1,10 +1,44 @@ -/* common header for syslogd */ +/* common header for syslogd + * Copyright 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. + */ +#ifndef SYSLOGD_H_INCLUDED +#define SYSLOGD_H_INCLUDED 1 + +#include "syslogd-types.h" + #if defined(__GLIBC__) #define dprintf mydprintf #endif /* __GLIBC__ */ + void dprintf(char *, ...); void logerror(char *type); void logerrorSz(char *type, char *errMsg); void logerrorInt(char *type, int iErr); +void getCurrTime(struct syslogTime *t); +int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst); +int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf); +int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf); + +extern int glblHadMemShortage; /* indicates if we had memory shortage some time during the run */ +extern syslogCODE rs_prioritynames[]; +extern syslogCODE rs_facilitynames[]; + #include "rsyslog.h" +#endif /* #ifndef SYSLOGD_H_INCLUDED */ |