summaryrefslogtreecommitdiffstats
path: root/omfwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'omfwd.c')
-rw-r--r--omfwd.c326
1 files changed, 184 insertions, 142 deletions
diff --git a/omfwd.c b/omfwd.c
index 122dfba1..db5750b4 100644
--- a/omfwd.c
+++ b/omfwd.c
@@ -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")) {