internal restructuring in omfwd.c - stage work for further modularization I

think I also fixed a bug as a side-effect - but not looked to much at
    it
This commit is contained in:
Rainer Gerhards 2007-12-27 17:32:10 +00:00
parent cebbf6d44e
commit bcdb6dcfd7
3 changed files with 187 additions and 152 deletions

326
omfwd.c
View File

@ -116,13 +116,172 @@ typedef struct _instanceData {
#ifdef USE_GSSAPI
static char *gss_base_service_name = NULL;
static enum gss_mode_t {
GSSMODE_NONE,
GSSMODE_NONE, /* GSSAPI is NOT support (aka "we use plain tcp") - the default */
GSSMODE_MIC,
GSSMODE_ENC
} gss_mode;
#endif
/* ----------------------------------------------------------------- *
* CODE THAT SHALL GO INTO ITS OWN MODULE *
* ----------------------------------------------------------------- */
/* get the syslog forward port from selector_t. The passed in
* struct must be one that is setup for forwarding.
* rgerhards, 2007-06-28
* We may change the implementation to try to lookup the port
* if it is unspecified. So far, we use the IANA default auf 514.
*/
static char *getFwdSyslogPt(instanceData *pData)
{
assert(pData != NULL);
if(pData->port == NULL)
return("514");
else
return(pData->port);
}
/* Build frame based on selected framing */
static rsRetVal TCPSendBldFrame(instanceData *pData, char **pmsg, size_t *plen, int *pbMustBeFreed, int *pbIsCompressed)
{
DEFiRet;
TCPFRAMINGMODE framingToUse;
size_t len;
char *msg;
char *buf = NULL; /* if this is non-NULL, it MUST be freed before return! */
assert(plen != NULL);
assert(pbIsCompressed != NULL);
assert(pbMustBeFreed != NULL);
assert(pmsg != NULL);
msg = *pmsg;
len = *plen;
*pbIsCompressed = *msg == 'z'; /* cache this, so that we can modify the message buffer */
/* select framing for this record. If we have a compressed record, we always need to
* use octet counting because the data potentially contains all control characters
* including LF.
*/
framingToUse = *pbIsCompressed ? TCP_FRAMING_OCTET_COUNTING : pData->tcp_framing;
/* now check if we need to add a line terminator. We need to
* copy the string in memory in this case, this is probably
* quicker than using writev and definitely quicker than doing
* two socket calls.
* rgerhards 2005-07-22
*
* Some messages already contain a \n character at the end
* of the message. We append one only if we there is not
* already one. This seems the best fit, though this also
* means the message does not arrive unaltered at the final
* destination. But in the spirit of legacy syslog, this is
* probably the best to do...
* rgerhards 2005-07-20
*/
/* Build frame based on selected framing */
if(framingToUse == TCP_FRAMING_OCTET_STUFFING) {
if((*(msg+len-1) != '\n')) {
/* in the malloc below, we need to add 2 to the length. The
* reason is that we a) add one character and b) len does
* not take care of the '\0' byte. Up until today, it was just
* +1 , which caused rsyslogd to sometimes dump core.
* I have added this comment so that the logic is not accidently
* changed again. rgerhards, 2005-10-25
*/
if((buf = malloc((len + 2) * sizeof(char))) == NULL) {
/* extreme mem shortage, try to solve
* as good as we can. No point in calling
* any alarms, they might as well run out
* of memory (the risk is very high, so we
* do NOT risk that). If we have a message of
* more than 1 byte (what I guess), we simply
* overwrite the last character.
* rgerhards 2005-07-22
*/
if(len > 1) {
*(msg+len-1) = '\n';
} else {
/* we simply can not do anything in
* this case (its an error anyhow...).
*/
}
} else {
/* we got memory, so we can copy the message */
memcpy(buf, msg, len); /* do not copy '\0' */
*(buf+len) = '\n';
*(buf+len+1) = '\0';
msg = buf; /* use new one */
++len; /* care for the \n */
}
}
} else {
/* Octect-Counting
* In this case, we need to always allocate a buffer. This is because
* we need to put a header in front of the message text
*/
char szLenBuf[16];
int iLenBuf;
/* important: the printf-mask is "%d<sp>" because there must be a
* space after the len!
*//* The chairs of the IETF syslog-sec WG have announced that it is
* consensus to do the octet count on the SYSLOG-MSG part only. I am
* now changing the code to reflect this. Hopefully, it will not change
* once again (there can no compatibility layer programmed for this).
* To be on the save side, I just comment the code out. I mark these
* comments with "IETF20061218".
* rgerhards, 2006-12-19
*/
iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", (int) len);
/* IETF20061218 iLenBuf =
snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", len + iLenBuf);*/
if((buf = malloc((len + iLenBuf) * sizeof(char))) == NULL) {
/* we are out of memory. This is an extreme situation. We do not
* call any alarm handlers because they most likely run out of mem,
* too. We are brave enough to call debug output, though. Other than
* that, there is nothing left to do. We can not sent the message (as
* in case of the other framing, because the message is incomplete.
* We could, however, send two chunks (header and text separate), but
* that would cause a lot of complexity in the code. So we think it
* is appropriate enough to just make sure we do not crash in this
* very unlikely case. For this, it is justified just to loose
* the message. Rgerhards, 2006-12-07
*/
dbgprintf("Error: out of memory when building TCP octet-counted "
"frame. Message is lost, trying to continue.\n");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
memcpy(buf, szLenBuf, iLenBuf); /* header */
memcpy(buf + iLenBuf, msg, len); /* message */
len += iLenBuf; /* new message size */
msg = buf; /* set message buffer */
}
/* frame building complete, on to actual sending */
*plen = len;
if(buf == NULL) {
/* msg not modified */
*pbMustBeFreed = 0;
} else {
*pmsg = msg;
*pbMustBeFreed = 1;
}
finalize_it:
return iRet;
}
/* ----------------------------------------------------------------- *
* END OF CODE THAT SHALL GO INTO ITS OWN MODULE *
* ----------------------------------------------------------------- */
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
@ -466,25 +625,21 @@ static int TCPSendGSSSend(instanceData *pData, char *msg, size_t len)
*/
static int TCPSend(instanceData *pData, char *msg, size_t len)
{
DEFiRet;
int retry = 0;
int done = 0;
int bIsCompressed;
int lenSend;
char *buf = NULL; /* if this is non-NULL, it MUST be freed before return! */
TCPFRAMINGMODE framingToUse;
int bMsgMustBeFreed = 0;/* must msg be freed at end of function? 0 - no, 1 - yes */
assert(pData != NULL);
assert(msg != NULL);
assert(len > 0);
bIsCompressed = *msg == 'z'; /* cache this, so that we can modify the message buffer */
/* select framing for this record. If we have a compressed record, we always need to
* use octet counting because the data potentially contains all control characters
* including LF.
*/
framingToUse = bIsCompressed ? TCP_FRAMING_OCTET_COUNTING : pData->tcp_framing;
iRet = TCPSendBldFrame(pData, &msg, &len, &bMsgMustBeFreed, &bIsCompressed);
if(iRet != RS_RET_OK)
return -1; /* TODO: change this code */
do { /* try to send message */
while(1) { /* loop is broken when send succeeds or error occurs */
if(pData->sock <= 0) {
/* we need to open the socket first */
# ifdef USE_GSSAPI
@ -496,111 +651,12 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
if((pData->sock = TCPSendCreateSocket(pData, pData->f_addr)) <= 0)
return -1;
}
/* now check if we need to add a line terminator. We need to
* copy the string in memory in this case, this is probably
* quicker than using writev and definitely quicker than doing
* two socket calls.
* rgerhards 2005-07-22
*
* Some messages already contain a \n character at the end
* of the message. We append one only if we there is not
* already one. This seems the best fit, though this also
* means the message does not arrive unaltered at the final
* destination. But in the spirit of legacy syslog, this is
* probably the best to do...
* rgerhards 2005-07-20
*/
/* Build frame based on selected framing */
if(framingToUse == TCP_FRAMING_OCTET_STUFFING) {
if((*(msg+len-1) != '\n')) {
if(buf != NULL)
free(buf);
/* in the malloc below, we need to add 2 to the length. The
* reason is that we a) add one character and b) len does
* not take care of the '\0' byte. Up until today, it was just
* +1 , which caused rsyslogd to sometimes dump core.
* I have added this comment so that the logic is not accidently
* changed again. rgerhards, 2005-10-25
*/
if((buf = malloc((len + 2) * sizeof(char))) == NULL) {
/* extreme mem shortage, try to solve
* as good as we can. No point in calling
* any alarms, they might as well run out
* of memory (the risk is very high, so we
* do NOT risk that). If we have a message of
* more than 1 byte (what I guess), we simply
* overwrite the last character.
* rgerhards 2005-07-22
*/
if(len > 1) {
*(msg+len-1) = '\n';
} else {
/* we simply can not do anything in
* this case (its an error anyhow...).
*/
}
} else {
/* we got memory, so we can copy the message */
memcpy(buf, msg, len); /* do not copy '\0' */
*(buf+len) = '\n';
*(buf+len+1) = '\0';
msg = buf; /* use new one */
++len; /* care for the \n */
}
}
} else {
/* Octect-Counting
* In this case, we need to always allocate a buffer. This is because
* we need to put a header in front of the message text
*/
char szLenBuf[16];
int iLenBuf;
/* important: the printf-mask is "%d<sp>" because there must be a
* space after the len!
*//* The chairs of the IETF syslog-sec WG have announced that it is
* consensus to do the octet count on the SYSLOG-MSG part only. I am
* now changing the code to reflect this. Hopefully, it will not change
* once again (there can no compatibility layer programmed for this).
* To be on the save side, I just comment the code out. I mark these
* comments with "IETF20061218".
* rgerhards, 2006-12-19
*/
iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", (int) len);
/* IETF20061218 iLenBuf =
snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", len + iLenBuf);*/
if((buf = malloc((len + iLenBuf) * sizeof(char))) == NULL) {
/* we are out of memory. This is an extreme situation. We do not
* call any alarm handlers because they most likely run out of mem,
* too. We are brave enough to call debug output, though. Other than
* that, there is nothing left to do. We can not sent the message (as
* in case of the other framing, because the message is incomplete.
* We could, however, send two chunks (header and text separate), but
* that would cause a lot of complexity in the code. So we think it
* is appropriate enough to just make sure we do not crash in this
* very unlikely case. For this, it is justified just to loose
* the message. Rgerhards, 2006-12-07
*/
dbgprintf("Error: out of memory when building TCP octet-counted "
"frame. Message is lost, trying to continue.\n");
return 0;
}
memcpy(buf, szLenBuf, iLenBuf); /* header */
memcpy(buf + iLenBuf, msg, len); /* message */
len += iLenBuf; /* new message size */
msg = buf; /* set message buffer */
}
/* frame building complete, on to actual sending */
# ifdef USE_GSSAPI
if(gss_mode != GSSMODE_NONE) {
if(TCPSendGSSSend(pData, msg, len) == 0) {
if(buf != NULL) {
free(buf);
if(bMsgMustBeFreed) {
free(msg);
}
return 0;
} else {
@ -609,8 +665,8 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
/* try to recover */
continue;
} else {
if(buf != NULL)
free(buf);
if(bMsgMustBeFreed)
free(msg);
dbgprintf("message not (tcp)send");
return -1;
}
@ -622,8 +678,8 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
bIsCompressed ? "***compressed***" : msg);
if((unsigned)lenSend == len) {
/* all well */
if(buf != NULL) {
free(buf);
if(bMsgMustBeFreed) {
free(msg);
}
return 0;
} else if(lenSend != -1) {
@ -633,8 +689,8 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
*/
dbgprintf("message not completely (tcp)send, ignoring %d\n", lenSend);
usleep(1000); /* experimental - might be benefitial in this situation */
if(buf != NULL)
free(buf);
if(bMsgMustBeFreed)
free(msg);
return 0;
}
@ -642,8 +698,8 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
case EMSGSIZE:
dbgprintf("message not (tcp)send, too large\n");
/* This is not a real error, so it is not flagged as one */
if(buf != NULL)
free(buf);
if(bMsgMustBeFreed)
free(msg);
return 0;
break;
default:
@ -657,38 +713,22 @@ static int TCPSend(instanceData *pData, char *msg, size_t len)
close(pData->sock);
pData->sock = -1;
} else {
if(buf != NULL)
free(buf);
if(bMsgMustBeFreed)
free(msg);
return -1;
}
# ifdef USE_GSSAPI
}
# endif
} while(!done); /* warning: do ... while() */
}
/*NOT REACHED*/
if(buf != NULL)
free(buf);
if(bMsgMustBeFreed)
free(msg);
return -1; /* only to avoid compiler warning! */
}
/* get the syslog forward port from selector_t. The passed in
* struct must be one that is setup for forwarding.
* rgerhards, 2007-06-28
* We may change the implementation to try to lookup the port
* if it is unspecified. So far, we use the IANA default auf 514.
*/
static char *getFwdSyslogPt(instanceData *pData)
{
assert(pData != NULL);
if(pData->port == NULL)
return("514");
else
return(pData->port);
}
/* try to resume connection if it is not ready
* rgerhards, 2007-08-02
*/
@ -837,6 +877,7 @@ dbgprintf("UDP send socket not yet initialized, doing it now\n");
pData->eDestState = eDestFORW_SUSP;
iRet = RS_RET_SUSPENDED;
}
dbgprintf("forwarded\n");
}
}
break;
@ -1026,6 +1067,7 @@ ENDqueryEtryPt
#ifdef USE_GSSAPI
/* set a new GSSMODE based on config directive */
static rsRetVal setGSSMode(void __attribute__((unused)) *pVal, uchar *mode)
{
if (!strcmp((char *) mode, "none")) {

View File

@ -204,12 +204,6 @@ dbgprintf("imtcp: bEnableTCP %d\n", bEnableTCP);
#endif
if (bEnableTCP) {
if(sockTCPLstn == NULL) {
/* even when doing a re-init, we do not shut down and
* re-open the TCP socket. That would break existing TCP
* session, which we do not desire. Should at some time arise
* need to do that, I recommend controlling that via a
* user-selectable option. rgerhards, 2007-06-21
*/
# ifdef USE_GSSAPI
if(bEnableTCP & ALLOWEDMETHOD_GSS) {
if(TCPSessGSSInit()) {
@ -230,13 +224,11 @@ ENDwillRun
BEGINafterRun
CODESTARTafterRun
/* do cleanup here */
dbgprintf("call clearAllowedSenders(0x%lx)\n", (unsigned long) pAllowedSenders_TCP);
if (pAllowedSenders_TCP != NULL) {
clearAllowedSenders (pAllowedSenders_TCP);
pAllowedSenders_TCP = NULL;
}
#ifdef USE_GSSAPI
dbgprintf("call clearAllowedSenders(0x%lx)\n", (unsigned long) pAllowedSenders_GSS);
if (pAllowedSenders_GSS != NULL) {
clearAllowedSenders (pAllowedSenders_GSS);
pAllowedSenders_GSS = NULL;
@ -290,8 +282,6 @@ CODESTARTmodInit
*ipIFVersProvided = 1; /* so far, we only support the initial definition */
CODEmodInit_QueryRegCFSLineHdlr
/* register config file handlers */
//CHKiRet(omsdRegCFSLineHdlr((uchar *)"omitlocallogging", 0, eCmdHdlrBinary,
// NULL, &bOmitLocalLogging, STD_LOADABLE_MODULE_ID));
#if defined(USE_GSSAPI)
CHKiRet(regCfSysLineHdlr((uchar *)"gsslistenservicename", 0, eCmdHdlrGetWord, NULL, &gss_listen_service_name, NULL));
#endif

View File

@ -744,6 +744,7 @@ int TCPSessDataRcvd(int iTCPSess, char *pData, int iLen)
#ifdef USE_GSSAPI
/* returns 0 if all went OK, -1 if it failed */
int TCPSessGSSInit(void)
{
gss_buffer_desc name_buf;
@ -775,6 +776,7 @@ int TCPSessGSSInit(void)
}
/* returns 0 if all went OK, -1 if it failed */
int TCPSessGSSAccept(int fd)
{
gss_buffer_desc send_tok, recv_tok;
@ -937,6 +939,7 @@ int TCPSessGSSAccept(int fd)
}
/* returns: ? */
int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len)
{
gss_buffer_desc xmit_buf, msg_buf;