aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryaworsky <yaworsky>2005-10-26 04:59:51 +0000
committeryaworsky <yaworsky>2005-10-26 04:59:51 +0000
commit0f6fa595431267af5550a1b937b20f68957ca33f (patch)
tree0f7d4fab32930067e9b751e2df518df9997804d4
parent2bc65a6d5b3aa6c33e0322b6bcb786841859262b (diff)
downloadsyslog-win32-0f6fa595431267af5550a1b937b20f68957ca33f.tar.gz
syslog-win32-0f6fa595431267af5550a1b937b20f68957ca33f.tar.xz
syslog-win32-0f6fa595431267af5550a1b937b20f68957ca33f.zip
Implemented relaying.
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/conf.c85
-rwxr-xr-xdaemon/dest_relay.c195
-rw-r--r--daemon/syslogd.h11
-rw-r--r--doc/src/configuration.xml49
5 files changed, 318 insertions, 24 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 81fddfa..06c1ccc 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -13,7 +13,7 @@ endif
AM_CPPFLAGS += -I. -I../include $(GLIB_CFLAGS)
bin_PROGRAMS = syslogd
-syslogd_SOURCES = conf.c dest_file.c fifo.c listener.c logrotate.c \
+syslogd_SOURCES = conf.c dest_file.c dest_relay.c fifo.c listener.c logrotate.c \
main.c names.c pathnames.c purger.c syslogd.c syslogd.h
syslogd_LDADD = -lws2_32 $(GLIB_LIBS)
diff --git a/daemon/conf.c b/daemon/conf.c
index 9dfb248..c31115b 100644
--- a/daemon/conf.c
+++ b/daemon/conf.c
@@ -125,8 +125,7 @@ static void create_source( int line_number,
/******************************************************************************
* init_file_dest
*
- * read attributes of element, initialize destination structure and append
- * it to the list of destinations
+ * read attributes of element and initialize destination structure
*/
static gboolean init_file_dest( struct destination *dest,
int line_number,
@@ -203,6 +202,46 @@ static gboolean init_file_dest( struct destination *dest,
}
/******************************************************************************
+ * init_relay_dest
+ *
+ * read attributes of element and initialize destination structure
+ */
+static gboolean init_relay_dest( struct destination *dest,
+ int line_number,
+ const gchar** attribute_names,
+ const gchar** attribute_values )
+{
+ const gchar *aname;
+
+ for( ; (aname = *attribute_names) != NULL; attribute_names++, attribute_values++ )
+ {
+ const gchar *aval = *attribute_values;
+ if( strcmp( aname, "collector" ) == 0 )
+ dest->u.relay.collector = g_strdup( aval );
+ else if( strcmp( aname, "omit_hostname" ) == 0 )
+ {
+ if( strcmp( aval, "yes" ) == 0 )
+ dest->u.relay.omit_hostname = TRUE;
+ else if( strcmp( aval, "no" ) == 0 )
+ dest->u.relay.omit_hostname = FALSE;
+ else
+ {
+ dest->u.relay.omit_hostname = FALSE;
+ ERR( "Invalid value \"%s\" of attribute \"%s\" at line %d; assumed \"no\"\n",
+ aval, aname, line_number );
+ }
+ }
+ }
+ if( !dest->u.relay.collector )
+ {
+ ERR( "Undefined destination relay at line %d\n", line_number );
+ return FALSE;
+ }
+
+ return init_destination_relay( dest );
+}
+
+/******************************************************************************
* create_destination
*
* read attributes of element, initialize destination structure and append
@@ -231,6 +270,11 @@ static void create_destination( int line_number,
dest->type = DT_FILE;
break;
}
+ else if( strcmp( aname, "collector" ) == 0 )
+ {
+ dest->type = DT_RELAY;
+ break;
+ }
}
if( !dest->name )
{
@@ -245,6 +289,10 @@ static void create_destination( int line_number,
r = init_file_dest( dest, line_number, attribute_names, attribute_values );
break;
+ case DT_RELAY:
+ r = init_relay_dest( dest, line_number, attribute_names, attribute_values );
+ break;
+
default:
ERR( "Undefined destination type at line %d\n", line_number );
break;
@@ -734,17 +782,28 @@ static void dump_configuration()
for( item = destinations; item; item = item->next )
{
struct destination *d = item->data;
- TRACE( "\tname=%s\tfile=%s\n"
- "\t\trotate=%s size=%d backlogs=%d ifempty=%s\n"
- "\t\tolddir=%s compresscmd=%s\n",
- d->name, d->u.file.name_pattern,
- (d->u.file.rotate == RP_DAILY)? "daily"
- : (d->u.file.rotate == RP_WEEKLY)? "weekly"
- : (d->u.file.rotate == RP_MONTHLY)? "monthly"
- : "undefined",
- d->u.file.size, d->u.file.backlogs, d->u.file.ifempty? "yes" : "no",
- d->u.file.olddir? d->u.file.olddir : "NULL",
- d->u.file.compresscmd? d->u.file.compresscmd : "NULL" );
+ switch( d->type )
+ {
+ case DT_FILE:
+ TRACE( "\tname=%s\tfile=%s\n"
+ "\t\trotate=%s size=%d backlogs=%d ifempty=%s\n"
+ "\t\tolddir=%s compresscmd=%s\n",
+ d->name, d->u.file.name_pattern,
+ (d->u.file.rotate == RP_DAILY)? "daily"
+ : (d->u.file.rotate == RP_WEEKLY)? "weekly"
+ : (d->u.file.rotate == RP_MONTHLY)? "monthly"
+ : "undefined",
+ d->u.file.size, d->u.file.backlogs, d->u.file.ifempty? "yes" : "no",
+ d->u.file.olddir? d->u.file.olddir : "NULL",
+ d->u.file.compresscmd? d->u.file.compresscmd : "NULL" );
+ break;
+ case DT_RELAY:
+ TRACE( "\tname=%s\tcollector=%s\n"
+ "\t\tomit_hostname=%s\n",
+ d->name, d->u.file.name_pattern,
+ d->u.relay.omit_hostname? "yes" : "no" );
+ break;
+ }
}
TRACE( "Filters:\n" );
for( item = filters; item; item = item->next )
diff --git a/daemon/dest_relay.c b/daemon/dest_relay.c
new file mode 100755
index 0000000..4bea0c6
--- /dev/null
+++ b/daemon/dest_relay.c
@@ -0,0 +1,195 @@
+/*
+ * dest_relay.c - syslogd implementation for windows, relay destination
+ *
+ * Created by Alexander Yaworsky
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+
+#include <glib.h>
+
+#include <syslog.h>
+#include <syslogd.h>
+
+struct dest_extra
+{
+ SOCKADDR_IN addr;
+ SOCKET sock;
+};
+
+/******************************************************************************
+ * resolve_address
+ *
+ * Parse 'collector' parameter and init 'addr' in the dest_extra.
+ * Collector should contain host name or address optionally followed by colon
+ * and port number.
+ */
+static gboolean resolve_addr( struct destination* destination )
+{
+ struct dest_extra *extra = destination->extra;
+ gboolean ret = FALSE;
+ char *p;
+ gchar *host;
+ struct hostent *phe;
+
+ TRACE_ENTER( "destination=%s, collector=%s\n",
+ destination->name, destination->u.relay.collector );
+
+ memset( &extra->addr, 0, sizeof(SOCKADDR_IN) );
+ extra->addr.sin_family = AF_INET;
+
+ p = strchr( destination->u.relay.collector, ':' );
+ if( p )
+ host = g_strndup( destination->u.relay.collector,
+ p - destination->u.relay.collector );
+ else
+ host = g_strdup( destination->u.relay.collector );
+
+ phe = gethostbyname( host );
+ if( !phe )
+ {
+ ERR( "Cannot resolve hostname %s for destination %s\n",
+ destination->u.relay.collector, destination->name );
+ goto done;
+ }
+
+ memcpy( &extra->addr.sin_addr.s_addr, phe->h_addr, phe->h_length );
+
+ if( p )
+ extra->addr.sin_port = htons( (unsigned short) strtoul( p + 1, NULL, 0 ) );
+ else
+ extra->addr.sin_port = htons( SYSLOG_PORT );
+
+ TRACE( "collector=%d.%d.%d.%d:%d\n",
+ extra->addr.sin_addr.S_un.S_un_b.s_b1, extra->addr.sin_addr.S_un.S_un_b.s_b2,
+ extra->addr.sin_addr.S_un.S_un_b.s_b3, extra->addr.sin_addr.S_un.S_un_b.s_b4,
+ ntohs( extra->addr.sin_port ) );
+
+ ret = TRUE;
+
+done:
+ g_free( host );
+
+ TRACE_LEAVE( "done; ret=%d\n", ret );
+ return ret;
+}
+
+/******************************************************************************
+ * put_message_to_relay_dest
+ */
+static void put_message_to_relay_dest( struct destination* destination, struct message* msg )
+{
+ struct dest_extra *extra = destination->extra;
+ char pri[16];
+ gchar *buffer;
+ int len;
+
+ TRACE_ENTER( "msg=%p, destination=%s\n", msg, destination->name );
+
+ sprintf( pri, "<%d>", LOG_MAKEPRI( msg->facility, msg->priority ) );
+ if( destination->u.relay.omit_hostname )
+ buffer = g_strconcat( pri, msg->timestamp, " ", msg->message, "\n", NULL );
+ else
+ buffer = g_strconcat( pri, msg->timestamp, " ",
+ msg->hostname, " ", msg->message, "\n", NULL );
+
+ len = strlen( buffer );
+ if( len > 1024 )
+ {
+ buffer[ 1023 ] = '\n';
+ buffer[ 1024 ] = '\0';
+ len = 1024;
+ }
+ if( sendto( extra->sock, buffer, len, 0,
+ (SOCKADDR*) &extra->addr, sizeof(SOCKADDR_IN) ) == SOCKET_ERROR )
+ ERR( "sendto error %lu\n", WSAGetLastError() );
+
+ g_free( buffer );
+
+ TRACE_LEAVE( "done\n" );
+}
+
+/******************************************************************************
+ * finalize_relay_dest
+ *
+ * close socket
+ */
+static void finalize_relay_dest( struct destination* destination )
+{
+ struct dest_extra *extra = destination->extra;
+
+ TRACE_ENTER( "destination=%s\n", destination->name );
+ if( extra->sock != INVALID_SOCKET )
+ {
+ closesocket( extra->sock );
+ }
+ TRACE_LEAVE( "done\n" );
+}
+
+/******************************************************************************
+ * init_destination_relay
+ *
+ * initialize relay destination: resolve address of collector and create socket
+ */
+gboolean init_destination_relay( struct destination* destination )
+{
+ struct dest_extra *extra;
+ int n;
+
+ TRACE_ENTER( "destination=%s\n", destination->name );
+
+ extra = g_malloc( sizeof(struct dest_extra) );
+ destination->extra = extra;
+ destination->put = put_message_to_relay_dest;
+ destination->fini = finalize_relay_dest;
+ extra->sock = INVALID_SOCKET;
+
+ if( !resolve_addr( destination ) )
+ goto error;
+
+ for( n = 0;; n++ )
+ {
+ SOCKADDR_IN sa_local;
+
+ extra->sock = socket( AF_INET, SOCK_DGRAM, 0 );
+ if( INVALID_SOCKET == extra->sock )
+ {
+ ERR( "Cannot create socket\n" );
+ goto error;
+ }
+
+ memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
+ sa_local.sin_family = AF_INET;
+ if( bind( extra->sock, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 )
+ break;
+ closesocket( extra->sock );
+ extra->sock = INVALID_SOCKET;
+ if( n == 100 )
+ {
+ ERR( "Cannot bind socket\n" );
+ goto error;
+ }
+ Sleep(0);
+ }
+ TRACE_LEAVE( "ok\n" );
+ return TRUE;
+
+error:
+ if( extra->sock != INVALID_SOCKET )
+ closesocket( extra->sock );
+ g_free( destination->extra );
+ TRACE_LEAVE( "error\n" );
+ return FALSE;
+}
diff --git a/daemon/syslogd.h b/daemon/syslogd.h
index 8919ede..20dfa00 100644
--- a/daemon/syslogd.h
+++ b/daemon/syslogd.h
@@ -106,7 +106,8 @@ struct source
enum destination_type
{
DT_UNDEFINED,
- DT_FILE
+ DT_FILE,
+ DT_RELAY
};
enum rotation_period
@@ -130,6 +131,12 @@ struct destination_file
gchar *compressoptions;
};
+struct destination_relay
+{
+ gchar *collector;
+ gboolean omit_hostname;
+};
+
struct destination;
typedef void (*dest_put)( struct destination* destination, struct message* message );
@@ -142,6 +149,7 @@ struct destination
union
{
struct destination_file file;
+ struct destination_relay relay;
} u;
void *extra;
/* methods */
@@ -171,6 +179,7 @@ extern GList *logpaths;
extern gboolean read_configuration();
extern gboolean init_destination_file( struct destination* destination );
+extern gboolean init_destination_relay( struct destination* destination );
/* queue */
struct fifo_item
diff --git a/doc/src/configuration.xml b/doc/src/configuration.xml
index eddd098..a29a210 100644
--- a/doc/src/configuration.xml
+++ b/doc/src/configuration.xml
@@ -117,6 +117,9 @@ name
<para>
Required.
The name of the destination.
+The type of destination may be either <quote>file</quote> or <quote>relay</quote>.
+It is determined by the presence of attributes <quote>file</quote>
+or <quote>collector</quote> respectively.
</para>
</listitem>
</varlistentry>
@@ -126,8 +129,8 @@ file
</term>
<listitem>
<para>
-Required.
-The pattern for the file name.
+The presence of this attribute defines destination type as <quote>file</quote>.
+The value of attribute is a pattern for the file name.
It may contain the following format characters:
<segmentedlist>
<?dbhtml list-presentation="table"?>
@@ -156,7 +159,7 @@ rotate
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Rotate log files periodically.
Possible values are:
<emphasis>daily</emphasis>,
@@ -175,7 +178,7 @@ size
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Log files are rotated when they grow bigger then <emphasis>size</emphasis> bytes.
If size is followed by M, the size if assumed to be in megabytes.
If the k is used, the size is in kilobytes.
@@ -189,7 +192,7 @@ backlogs
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
If rotation is turned on this attribute specifies the number of backlog files.
</para>
</listitem>
@@ -200,7 +203,7 @@ ifempty
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Rotate the log file even if it is empty.
Possible values are: <emphasis>yes</emphasis>, <emphasis>no</emphasis>.
Default is <emphasis>yes</emphasis>.
@@ -213,7 +216,7 @@ olddir
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Logs are moved to this directory for rotation.
If value is a relative path then this directory will be located in the same
directory with syslogd executable.
@@ -226,7 +229,7 @@ compresscmd
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Command to use to compress log file.
</para>
</listitem>
@@ -237,13 +240,41 @@ compressoptions
</term>
<listitem>
<para>
-Optional.
+File-specific, optional.
Command line options may be passed to the compression program, if one is in use.
Options may contain $PATHNAME and $FILENAME substrings which will be replaced
with backlog pathname and basename respectively.
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+collector
+ </term>
+ <listitem>
+ <para>
+The presence of this attribute defines destination type as <quote>relay</quote>.
+The value of attribute is a name or IPv4 address of the collector optionally
+followed by the colon and port number.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+omit_hostname
+ </term>
+ <listitem>
+ <para>
+Relay-specific, optional.
+Do not include source hostname in the datagramm.
+Some syslog daemons by default do not rely on the hostname part of datagramm
+and insert actual sender hostname in the logged message.
+Note that ommiting hostname violates <ulink url="http://www.ietf.org/rfc/rfc3164.txt">RFC 3164</ulink>.
+Possible values are: <emphasis>yes</emphasis>, <emphasis>no</emphasis>.
+Default is <emphasis>no</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
</section>