From 0f6fa595431267af5550a1b937b20f68957ca33f Mon Sep 17 00:00:00 2001 From: yaworsky Date: Wed, 26 Oct 2005 04:59:51 +0000 Subject: Implemented relaying. --- daemon/Makefile.am | 2 +- daemon/conf.c | 85 ++++++++++++++++---- daemon/dest_relay.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ daemon/syslogd.h | 11 ++- doc/src/configuration.xml | 49 +++++++++--- 5 files changed, 318 insertions(+), 24 deletions(-) create mode 100755 daemon/dest_relay.c 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, @@ -202,6 +201,46 @@ static gboolean init_file_dest( struct destination *dest, return init_destination_file( 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 * @@ -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 +#include + +#include + +#include +#include + +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 Required. The name of the destination. +The type of destination may be either file or relay. +It is determined by the presence of attributes file +or collector respectively. @@ -126,8 +129,8 @@ file -Required. -The pattern for the file name. +The presence of this attribute defines destination type as file. +The value of attribute is a pattern for the file name. It may contain the following format characters: @@ -156,7 +159,7 @@ rotate -Optional. +File-specific, optional. Rotate log files periodically. Possible values are: daily, @@ -175,7 +178,7 @@ size -Optional. +File-specific, optional. Log files are rotated when they grow bigger then size 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 -Optional. +File-specific, optional. If rotation is turned on this attribute specifies the number of backlog files. @@ -200,7 +203,7 @@ ifempty -Optional. +File-specific, optional. Rotate the log file even if it is empty. Possible values are: yes, no. Default is yes. @@ -213,7 +216,7 @@ olddir -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 -Optional. +File-specific, optional. Command to use to compress log file. @@ -237,13 +240,41 @@ compressoptions -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. + + +collector + + + +The presence of this attribute defines destination type as relay. +The value of attribute is a name or IPv4 address of the collector optionally +followed by the colon and port number. + + + + + +omit_hostname + + + +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 RFC 3164. +Possible values are: yes, no. +Default is no + + + -- cgit v1.2.3