SYSLOG Collection Agent Source Code

#!/usr/bin/perl -w

###########################################################################
###                                                                     ###
###  NetworkLens SYSLOG Client                                          ###
###                                                                     ###
###  NetworkLens                                                        ###
###  Copyright (C) 2002, I-Link Incorporated                            ###
###                                                                     ###
###  This perl script will open a listening socket on the syslog port   ###
###  (port 514) and attempt to create new NetworkLens events from any   ###
###  message that arrive.                                               ###
###                                                                     ###
###  To Do:  (*) Check for new event vs. mod to existing event          ###
###              (rudimentary event correlation)                        ###
###                                                                     ###
###          (*) Provide some sort of filtering to remove events or     ###
###              messages that we don't care about                      ###
###                                                                     ###
###          (*) Make the signal handler abort immediately instead of   ###
###              just setting the "time_to_die" flag                    ###
###                                                                     ###
###  Change Log:                                                        ###
###                                                                     ###
###  12/17/2001  Greg Bailey                                            ###
###    Initial Version                                                  ###
###                                                                     ###
###  01/10/2002  Greg Bailey                                            ###
###    Change data for IP address to character string X.X.X.X           ###
###                                                                     ###
###########################################################################

###########################################################################
#    Configuration settings                                               #
###########################################################################

$debug = 0;

$dbi_datasource = "DBI:mysql:lens:localhost:3306";
$dbi_username   = "root";
$dbi_password   = "";

$MAXLINE = 1024;

###########################################################################
#    Package definitions                                                  #
###########################################################################

use DBI;
use IO::Socket;
use POSIX;

###########################################################################
#    Definitions from /usr/include/sys/syslog.h                           #
###########################################################################

$priority_map[0]  = "LOG_EMERG";
$priority_map[1]  = "LOG_ALERT";
$priority_map[2]  = "LOG_CRIT";
$priority_map[3]  = "LOG_ERR";
$priority_map[4]  = "LOG_WARNING";
$priority_map[5]  = "LOG_NOTICE";
$priority_map[6]  = "LOG_INFO";
$priority_map[7]  = "LOG_DEBUG";

$facility_map[0]  = "LOG_KERN";
$facility_map[1]  = "LOG_USER";
$facility_map[2]  = "LOG_MAIL";
$facility_map[3]  = "LOG_DAEMON";
$facility_map[4]  = "LOG_AUTH";
$facility_map[5]  = "LOG_SYSLOG";
$facility_map[6]  = "LOG_LPR";
$facility_map[7]  = "LOG_NEWS";
$facility_map[8]  = "LOG_UUCP";
$facility_map[9]  = "LOG_CRON";
$facility_map[10] = "LOG_AUTHPRIV";
$facility_map[11] = "LOG_FTP";
$facility_map[12] = "LOG_RESERVED";
$facility_map[13] = "LOG_RESERVED";
$facility_map[14] = "LOG_RESERVED";
$facility_map[15] = "LOG_RESERVED";
$facility_map[16] = "LOG_LOCAL0";
$facility_map[17] = "LOG_LOCAL1";
$facility_map[18] = "LOG_LOCAL2";
$facility_map[19] = "LOG_LOCAL3";
$facility_map[20] = "LOG_LOCAL4";
$facility_map[21] = "LOG_LOCAL5";
$facility_map[22] = "LOG_LOCAL6";
$facility_map[23] = "LOG_LOCAL7";

###########################################################################
#    Make a background process                                            #
###########################################################################

$pid = fork();
exit if $pid;
die "Couldn't fork: $1" unless defined( $pid );

POSIX::setsid()
  or die "Can't start a new session: $!";

$time_to_die = 0;

sub signal_handler
{
  $time_to_die = 1;
}

$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler;

###########################################################################
#    Connect to the NetworkLens database                                  #
###########################################################################

$dbh = DBI->connect( $dbi_datasource, $dbi_username, $dbi_password,
                     { RaiseError => 1 } )
  or die "connecting: $DBI::errstr\n";

###########################################################################
#    Open the syslog socket                                               #
###########################################################################

$syslog_socket = IO::Socket::INET->new( LocalPort => 'syslog', Proto => 'udp' )
  or die "socket: $@";

###########################################################################
#    Main Loop                                                            #
###########################################################################

until ( $time_to_die )
{
  $syslog_socket->recv( $syslog_message, $MAXLINE );

  $client_ip = $syslog_socket->peeraddr();
  $client_hostname = gethostbyaddr( $client_ip, AF_INET );
  $client_ip_address = $syslog_socket->peerhost();

  if ( $syslog_message =~ /^\<([0-9]*)\>(.*)$/ )
  {
    $code = $1;
    $message = $2;
    $priority = $code & 0x7;
    $facility = $code >> 3;
  }

  $message =~ s/(['"])/\\$1/g;

  ##---------------------------------------------------------------------##
  ##-  At this point, remove/filter events we don't care about...       -##
  ##---------------------------------------------------------------------##

  if ( $message =~ /^snmptrapd/ )
  {
    next;
  }

  ##---------------------------------------------------------------------##
  ##-  At this point, we want to create a new event                     -##
  ##---------------------------------------------------------------------##

  $summary = sprintf( "%s from %s<br>%s",
                      $facility_map[$facility], $client_hostname, $message );

  $sql = sprintf( "insert into lens_event "
                . "  ( status, severity, created, ip_addr, category, summary ) "
                . "values "
                . "  ( 0, %d, now(), '%s', 'SYSLOG', '%s' )",
                  $priority, $client_ip_address, $summary );

  if ( $debug )
  {
    printf( "id       = UNKNOWN\n" );
    printf( "status   = NEW\n" );
    printf( "code     = %s\n", $code );
    printf( "priority = %s\n", $priority_map[$priority] );
    printf( "facility = %s\n", $facility_map[$facility] );
    printf( "message  = %s\n", $message );
    printf( "SQL      = %s\n", $sql );
    printf( "\n" );
  }

  $dbh->do( $sql );
}

###########################################################################
#    Disconnect from the NetworkLens database                             #
###########################################################################

$dbh->disconnect()
  or die "disconnecting: $DBI::errstr\n";

###########################################################################
###  END OF SOURCE FILE                                                 ###
###########################################################################