summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-04 16:57:25 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-04 16:57:25 +0000
commit0d5d42c52228964d76996c0e58fdf69258436716 (patch)
tree0505b84f979f9e369eebce188046fd6c7ed5902c
parentee629c4f742ac904c4a5055e85ef86d6decfb344 (diff)
downloadrsyslog-0d5d42c52228964d76996c0e58fdf69258436716.tar.gz
rsyslog-0d5d42c52228964d76996c0e58fdf69258436716.tar.xz
rsyslog-0d5d42c52228964d76996c0e58fdf69258436716.zip
an initial, somewhat working, tester for the mail functionality
-rw-r--r--ChangeLog20
-rw-r--r--plugins/ommail/ommail.c215
-rw-r--r--rsyslog.h1
3 files changed, 232 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 35c71f85..7eb5ce35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,12 +44,30 @@ Version 3.15.0 (rgerhards), 2008-04-01
only installed if corresponding option is selected. Thanks to
Michael Biebl for pointing these problems out.
---------------------------------------------------------------------------
-Version 3.14.0 (rgerhards), 2008-04-02
+Version 3.14.1 (rgerhards), 2008-04-04
+- bugfix: some messages were emited without hostname
- bugfix: rsyslogd was no longer build by default; man pages are
only installed if corresponding option is selected. Thanks to
Michael Biebl for pointing these problems out.
+- bugfix: zero-length strings were not supported in object
+ deserializer
- disabled atomic operations for this stable build as it caused
platform problems
+- bugfix: memory leaks in script engine
+- bugfix: $hostname and $fromhost in RainerScript did not work
+- bugfix: some memory leak when queue is runing in disk mode
+- man pages improved thanks to varmofekoj and Peter Vrabec
+- We have removed the 32 character size limit (from RFC3164) on the
+ tag. This had bad effects on existing envrionments, as sysklogd didn't
+ obey it either (probably another bug in RFC3164...). We now receive
+ the full size, but will modify the outputs so that only 32 characters
+ max are used by default. If you need large tags in the output, you need
+ to provide custom templates.
+---------------------------------------------------------------------------
+Version 3.14.0 (rgerhards), 2008-04-02
+An interim version was accidently released to the web. It was named 3.14.0.
+To avoid confusion, we have not assigned this version number to any
+official release. If you happen to use 3.14.0, please update to 3.14.1.
---------------------------------------------------------------------------
Version 3.13.0-dev0 (rgerhards), 2008-03-31
- bugfix: accidently set debug option in 3.12.5 reset to production
diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c
index 57de7fc0..4da4f58c 100644
--- a/plugins/ommail/ommail.c
+++ b/plugins/ommail/ommail.c
@@ -33,9 +33,10 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
#include <errno.h>
-#include <ctype.h>
-#include <librelp.h>
+#include <netdb.h>
+#include <sys/socket.h>
#include "syslogd.h"
#include "syslogd-types.h"
#include "srUtils.h"
@@ -63,6 +64,9 @@ typedef struct _instanceData {
uchar *pszFrom;
uchar *pszTo;
uchar *pszSubject;
+ char RcvBuf[1024]; /* buffer for receiving server responses */
+ size_t lenRcvBuf;
+ size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */
int sock; /* socket to this server (most important when we do multiple msgs per mail) */
} smtp;
} md; /* mode-specific data */
@@ -104,6 +108,197 @@ CODESTARTdbgPrintInstInfo
ENDdbgPrintInstInfo
+/* TCP support code, should probably be moved to net.c or some place else... -- rgerhards, 2008-04-04 */
+
+/* "receive" a character from the remote server. A single character
+ * is returned. Returns RS_RET_NO_MORE_DATA if the server has closed
+ * the connection and RS_RET_IO_ERROR if something goes wrong. This
+ * is a blocking read.
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+getRcvChar(instanceData *pData, char *pC)
+{
+ DEFiRet;
+ ssize_t lenBuf;
+ assert(pData != NULL);
+
+ if(pData->md.smtp.iRcvBuf == pData->md.smtp.lenRcvBuf) { /* buffer empty? */
+ /* yes, we need to read the next server response */
+ do {
+ lenBuf = recv(pData->md.smtp.sock, pData->md.smtp.RcvBuf, sizeof(pData->md.smtp.RcvBuf), 0);
+ if(lenBuf == 0) {
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ } else if(lenBuf < 0) {
+ if(errno != EAGAIN) {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ } else {
+ /* good read */
+ pData->md.smtp.iRcvBuf = 0;
+ pData->md.smtp.lenRcvBuf = lenBuf;
+ }
+
+ } while(lenBuf < 1);
+ }
+
+ /* when we reach this point, we have a non-empty buffer */
+ *pC = pData->md.smtp.RcvBuf[pData->md.smtp.iRcvBuf++];
+
+finalize_it:
+ RETiRet;
+}
+
+
+#if 0
+/* Initialize TCP socket (for sender), new socket is returned in
+ * pSock if all goes well.
+ */
+static rsRetVal
+CreateSocket(struct addrinfo *addrDest, int *pSock)
+{
+ DEFiRet;
+ int fd;
+ struct addrinfo *r;
+ char errStr[1024];
+
+ r = addrDest;
+
+ while(r != NULL) {
+ fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(fd != -1) {
+ if(connect(fd, r->ai_addr, r->ai_addrlen) != 0) {
+ dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ } else {
+ *pSock = fd;
+ FINALIZE;
+ }
+ close(fd);
+ } else {
+ dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+ r = r->ai_next;
+ }
+
+ dbgprintf("no working socket could be obtained");
+ iRet = RS_RET_NO_SOCKET;
+
+finalize_it:
+ RETiRet;
+}
+#endif
+
+
+/* open a connection to the mail server
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+serverConnect(instanceData *pData)
+{
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+ char errStr[1024];
+
+ DEFiRet;
+ assert(pData != NULL);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo((char*)pData->md.smtp.pszSrv, (char*)pData->md.smtp.pszSrvPort, &hints, &res) != 0) {
+ dbgprintf("error %d in getaddrinfo\n", errno);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if((pData->md.smtp.sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if(connect(pData->md.smtp.sock, res->ai_addr, res->ai_addrlen) != 0) {
+ dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(pData->md.smtp.sock != -1) {
+ close(pData->md.smtp.sock);
+ pData->md.smtp.sock = -1;
+ }
+ }
+
+ RETiRet;
+}
+
+
+
+/* send text to the server, blocking send */
+static rsRetVal
+Send(int sock, char *msg, size_t len)
+{
+ DEFiRet;
+ size_t offsBuf = 0;
+ ssize_t lenSend;
+
+ assert(msg != NULL);
+
+ if(len == 0) /* it's valid, but does not make much sense ;) */
+ FINALIZE;
+
+ do {
+ lenSend = send(sock, msg + offsBuf, len - offsBuf, 0);
+ dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len);
+
+ if(lenSend == -1) {
+ if(errno != EAGAIN) {
+ dbgprintf("message not (tcp)send, errno %d", errno);
+ ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR);
+ }
+ } else if(lenSend != (ssize_t) len) {
+ offsBuf += len; /* on to next round... */
+ } else {
+ FINALIZE;
+ }
+ } while(1);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* send a message via SMTP
+ * TODO: care about the result codes, we can't do it that blindly ;)
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+sendSMTP(instanceData *pData, uchar *body)
+{
+ DEFiRet;
+
+ assert(pData != NULL);
+
+ CHKiRet(serverConnect(pData));
+ CHKiRet(Send(pData->md.smtp.sock, "HELO\r\n", 6));
+ CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <rgerhards@adiscon.com>\r\n", sizeof("MAIL FROM: <rgerhards@adiscon.com>\r\n") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <rgerhards@adiscon.com>\r\n", sizeof("RCPT TO: <rgerhards@adiscon.com>\r\n") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, body, strlen((char*) body)));
+ CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1));
+
+ close(pData->md.smtp.sock);
+ pData->md.smtp.sock = -1;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
/* connect to server
* rgerhards, 2008-04-04
*/
@@ -111,6 +306,10 @@ static rsRetVal doConnect(instanceData *pData)
{
DEFiRet;
+ iRet = serverConnect(pData);
+ if(iRet == RS_RET_IO_ERROR)
+ iRet = RS_RET_SUSPENDED;
+
RETiRet;
}
@@ -131,7 +330,7 @@ CODESTARTdoAction
/* forward */
iRet = sendSMTP(pData, ppString[0]);
- if(iRet != RELP_RET_OK) {
+ if(iRet != RS_RET_OK) {
/* error! */
dbgprintf("error sending mail, suspending\n");
iRet = RS_RET_SUSPENDED;
@@ -154,6 +353,16 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
if((iRet = createInstance(&pData)) != RS_RET_OK)
FINALIZE;
+ //pData->md.smtp.pszSrv = "172.19.2.10";
+ pData->md.smtp.pszSrv = "172.19.0.6";
+ pData->md.smtp.pszSrvPort = "25";
+ pData->md.smtp.pszFrom = "rgerhards@adiscon.com";
+ pData->md.smtp.pszTo = "rgerhards@adiscon.com";
+ pData->md.smtp.pszSubject = "rsyslog test message";
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_TraditionalForwardFormat"));
+
/* TODO: do we need to call freeInstance if we failed - this is a general question for
* all output modules. I'll address it later as the interface evolves. rgerhards, 2007-07-25
*/
diff --git a/rsyslog.h b/rsyslog.h
index 9fe162d5..56140aaf 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -167,6 +167,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */
RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */
RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */
+ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */