aboutsummaryrefslogtreecommitdiffstats
path: root/daemon/dest_relay.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/dest_relay.c')
-rwxr-xr-xdaemon/dest_relay.c195
1 files changed, 195 insertions, 0 deletions
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;
+}