summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2005-07-04 14:30:30 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2005-07-04 14:30:30 +0000
commit6fc327cf4b2044ad52c0bdf7f61f4fe8335d332e (patch)
tree0d7b128b101d77f4142614d38ad6968876b98137
parent8ab54c554dc1576e21cdf8694063db3f96e111f1 (diff)
downloadrsyslog-6fc327cf4b2044ad52c0bdf7f61f4fe8335d332e.tar.gz
rsyslog-6fc327cf4b2044ad52c0bdf7f61f4fe8335d332e.tar.xz
rsyslog-6fc327cf4b2044ad52c0bdf7f61f4fe8335d332e.zip
on the way to syslog/tcp receiver...
-rw-r--r--NEWS23
-rw-r--r--syslogd.c285
2 files changed, 280 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index 32022f95..a3d0f98c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,10 @@
---------------------------------------------------------------------------
-Version 0.9.2 (RGer)
+Version 0.9.2 (RGer), around 2005-07-05
- changed the max supported message size to 32K. This is to satisfy
the needs of the IHE (Integrating the Healthcare Environment)
initiative. They use syslog for auditing and may generate messages
that large.
+- begun a simple TCP syslog receiver
---------------------------------------------------------------------------
Version 0.9.1 (RGer)
@@ -507,4 +508,24 @@ helpful.
* Don't return a closed fd if `-a' is called with a wrong path.
* Thanks to Bill Nottingham <notting@redhat.com> for providing
* a patch.
+ *
+ * The following copyright and license applies to the original
+ * sysklogd package that was used as a basis for this release of
+ * rsyslogd. Obviously, it applies to those parts stemming directly
+ * back to the original sysklogd package.
+ *
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
diff --git a/syslogd.c b/syslogd.c
index 1834a8fd..c485c7b7 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -81,26 +81,6 @@
* 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.
- *
- * The following copyright and license applies to the original
- * sysklogd package that was used as a basis for this release of
- * rsyslogd. Obviously, it applies to those parts stemming directly
- * back to the original sysklogd package.
- *
- * Copyright (c) 1983, 1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if !defined(lint) && !defined(NO_SCCS)
@@ -577,7 +557,6 @@ int Initialized = 0; /* set when we have initialized ourselves
* such a case.
*/
-
extern int errno;
/* hardcoded standard templates (used for defaults) */
@@ -627,9 +606,192 @@ void getCurrTime(struct syslogTime *t);
void cflineSetTemplateAndIOV(struct filed *f, char *pTemplateName);
#ifdef SYSLOG_UNIXAF
-static int create_inet_socket();
+static int create_udp_socket();
#endif
+/********************************************************************
+ * ### SYSLOG/TCP CODE ###
+ * This is code for syslog/tcp. This code would belong to a separate
+ * file - but I have put it here to avoid hassle with CVS. Over
+ * time, I expect rsyslog to utilize liblogging for actual network
+ * I/O. So the tcp code will be (re)moved some time. I don't like
+ * to add a new file to cvs that I will push to the attic in just
+ * a few weeks (month at most...). So I simply add the code here.
+ *
+ * Place no unrelated code between this comment and the
+ * END tcp comment!
+ *
+ * 2005-07-04 RGerhards (Happy independence day to our US friends!)
+ ********************************************************************/
+#ifdef SYSLOG_INET
+
+#define TCPSESS_MAX 100 /* TODO: remove hardcoded limit */
+static int sockTCPLstn = -1;
+struct TCPSession {
+ int sock;
+ char msg[MAXLINE];
+} TCPSessions[TCPSESS_MAX];
+
+
+/* Initialize the session table
+ */
+void TCPSessInit(void)
+{
+ register int i;
+
+ for(i = 0 ; i < TCPSESS_MAX ; ++i) {
+ TCPSessions[i].sock = -1; /* no sock */
+ TCPSessions[i].msg[0] = '\0'; /* just make sure... */
+ }
+}
+
+
+/* find a free spot in the session table. If the table
+ * is full, -1 is returned, else the index of the free
+ * entry (0 or higher).
+ */
+int TCPSessFindFreeSpot(void)
+{
+ register int i;
+
+ for(i = 0 ; i < TCPSESS_MAX ; ++i) {
+ if(TCPSessions[i].sock == -1)
+ break;
+ }
+
+ return((i < TCPSESS_MAX) ? i : -1);
+}
+
+
+/* Get the next session index. Free session tables entries are
+ * skipped. This function is provided the index of the last
+ * session entry, or -1 if no previous entry was obtained. It
+ * returns the index of the next session or -1, if there is no
+ * further entry in the table. Please note that the initial call
+ * might as well return -1, if there is no session at all in the
+ * session table.
+ */
+int TCPSessGetNxtSess(int iCurr)
+{
+ register int i;
+
+ for(i = iCurr + 1 ; i < TCPSESS_MAX ; ++i)
+ if(TCPSessions[i].sock != -1)
+ break;
+
+ return((i < TCPSESS_MAX) ? i : -1);
+}
+
+
+/* Initialize TCP sockets
+ */
+static int create_tcp_socket(void)
+{
+ int fd, on = 1;
+ struct sockaddr_in sin;
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ logerror("syslog: TCP: Unknown protocol, suspending tcp inet service.");
+ return fd;
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = 514; /* TODO: get this from a variable!!! */
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
+ (char *) &on, sizeof(on)) < 0 ) {
+ logerror("setsockopt(REUSEADDR), suspending tcp inet");
+ close(fd);
+ return -1;
+ }
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#ifndef BSD
+ if (setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, \
+ (char *) &on, sizeof(on)) < 0) {
+ logerror("setsockopt(BSDCOMPAT), suspending tcp inet");
+ close(fd);
+ return -1;
+ }
+#endif
+ if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ logerror("bind, suspending tcp inet");
+ close(fd);
+ return -1;
+ }
+
+ if(listen(fd, 5) < 0) {
+ logerror("listen, suspending tcp inet");
+ close(fd);
+ return -1;
+ }
+
+ sockTCPLstn = fd;
+
+ /* OK, we had success. Now it is also time to
+ * initialize our connections
+ */
+ TCPSessInit();
+
+ printf("Opened TCP socket %d.\n", sockTCPLstn);
+
+ return fd;
+}
+
+/* Accept new TCP connection; make entry in session table. If there
+ * is no more space left in the connection table, the new TCP
+ * connection is immediately dropped.
+ */
+void TCPSessAccept(void)
+{
+ int newConn;
+ int iSess;
+ newConn = accept(sockTCPLstn, NULL, NULL);
+ if (newConn < 0) {
+ logerror("tcp accept, ignoring error");
+ return;
+ }
+ /* TODO: must change to nonblocking? */
+
+ /* Add to session list */
+ iSess = TCPSessFindFreeSpot();
+ if(iSess == -1) {
+ errno = 0;
+ logerror("too many tcp sessions - dropping incoming request");
+ close(newConn);
+ return;
+ }
+
+ /* OK, we have a "good" index... */
+ TCPSessions[iSess].sock = newConn;
+ TCPSessions[iSess].msg[0] = '\0'; /* init msg buffer! */
+}
+
+
+/* Closes a TCP session and marks its slot in the session
+ * table as unused. No attention is paid to the return code
+ * of close, so potential-double closes are not detected.
+ */
+void TCPSessClose(int iSess)
+{
+ if(iSess < 0 || iSess > TCPSESS_MAX) {
+ errno = 0;
+ logerror("internal error, trying to close an invalid TCP session!");
+ return;
+ }
+
+ close(TCPSessions[iSess].sock);
+ TCPSessions[iSess].sock = -1;
+}
+
+#endif
+/********************************************************************
+ * ### END OF SYSLOG/TCP CODE ###
+ ********************************************************************/
+
/*******************************************************************
* BEGIN CODE-LIBLOGGING *
@@ -1680,6 +1842,7 @@ int main(argc, argv)
#ifdef SYSLOG_INET
struct sockaddr_in frominet;
char *from;
+ int iTCPSess;
#endif
pid_t ppid = getpid();
#endif
@@ -1901,7 +2064,7 @@ int main(argc, argv)
if ( Debug )
{
dprintf("Debugging disabled, SIGUSR1 to turn on debugging.\n");
- debugging_on = 0;
+ // TODO: ADD LATER: debugging_on = 0;
}
/*
* Send a signal to the parent to it can terminate.
@@ -1942,6 +2105,23 @@ int main(argc, argv)
if (inetm>maxfds) maxfds=inetm;
dprintf("Listening on syslog UDP port.\n");
}
+
+ /* Add the TCP socket to the list of read descriptors.
+ */
+ FD_SET(sockTCPLstn, &readfds);
+ if (sockTCPLstn>maxfds) maxfds=sockTCPLstn;
+ dprintf("Listening on syslog TCP port.\n");
+ /* do the sessions */
+ iTCPSess = TCPSessGetNxtSess(-1);
+ while(iTCPSess != -1) {
+ int fd;
+ fd = TCPSessions[iTCPSess].sock;
+ dprintf("Adding TCP Session %d\n", fd);
+ FD_SET(fd, &readfds);
+ if (fd>maxfds) maxfds=fd;
+ /* now get next... */
+ iTCPSess = TCPSessGetNxtSess(iTCPSess);
+ }
#endif
#endif
#ifdef TESTING
@@ -2014,7 +2194,7 @@ int main(argc, argv)
memset(line, '\0', sizeof(line));
i = recvfrom(finet, line, MAXLINE - 2, 0, \
(struct sockaddr *) &frominet, &len);
- dprintf("Message from inetd socket: #%d, host: %s\n",
+ dprintf("Message from UDP inetd socket: #%d, host: %s\n",
inetm, inet_ntoa(frominet.sin_addr));
if (i > 0) {
line[i] = line[i+1] = '\0';
@@ -2038,6 +2218,44 @@ int main(argc, argv)
sleep(10);
}
}
+
+ /* Now check for TCP */
+ if(FD_ISSET(sockTCPLstn, &readfds)) {
+ dprintf("New connect on TCP inetd socket: #%d\n", sockTCPLstn);
+ TCPSessAccept();
+ }
+
+ /* now check the sessions */
+ /* TODO: optimize the whole thing. We could stop enumerating as
+ * soon as we have found all sockets flagged as active. */
+ iTCPSess = TCPSessGetNxtSess(-1);
+ while(iTCPSess != -1) {
+ int fd;
+ int state;
+ fd = TCPSessions[iTCPSess].sock;
+ if(FD_ISSET(fd, &readfds)) {
+ char buf[MAXLINE];
+ dprintf("tcp session socket with new data: #%d\n", fd);
+
+ /* Receive message */
+ state = recv(fd, buf, sizeof(buf), 0);
+ printf("recv state %d\n", state);
+ if(state == 0) {
+ /* Session closed */
+ TCPSessClose(iTCPSess);
+ } else if(state == -1) {
+ /*TODO: good error message */
+ logerror("TCP session - session will be closed, error ignored");
+ /* fd);*/
+ TCPSessClose(iTCPSess);
+ } else {
+ /* valid data received, process it! */
+ dprintf("Data received: '%s'\n", buf);
+ }
+ getchar();
+ }
+ iTCPSess = TCPSessGetNxtSess(iTCPSess);
+ }
#endif
#else
if ( FD_ISSET(fileno(stdin), &readfds) ) {
@@ -2101,7 +2319,7 @@ static int create_unix_socket(const char *path)
#endif
#ifdef SYSLOG_INET
-static int create_inet_socket()
+static int create_udp_socket()
{
int fd, on = 1;
struct sockaddr_in sin;
@@ -3597,8 +3815,12 @@ void die(sig)
for (i = 0; i < nfunix; i++)
if (funix[i] != -1)
close(funix[i]);
- /* Close the inet socket. */
+ /* Close the UDP inet socket. */
if (InetInuse) close(inetm);
+ /* Close the TCP inet socket. */
+ /* TODO: close all TCP connections! */
+
+ if (InetInuse) close(sockTCPLstn);
/* Clean-up files. */
for (i = 0; i < nfunix; i++)
@@ -3895,9 +4117,18 @@ void init()
#endif
#ifdef SYSLOG_INET
+ if (1) { /* TODO: create a real condition! */
+ if (sockTCPLstn < 0) {
+ sockTCPLstn = create_tcp_socket();
+ if (sockTCPLstn >= 0) {
+ dprintf("Opened syslog TCP port.\n");
+ }
+ }
+ }
+
if (Forwarding || AcceptRemote) {
if (finet < 0) {
- finet = create_inet_socket();
+ finet = create_udp_socket();
if (finet >= 0) {
InetInuse = 1;
dprintf("Opened syslog UDP port.\n");