#! /usr/bin/perl -w

# vim:syntax=perl

use strict;
use lib '/usr/local/share/perl5';
use Lire::DlfSchema;
use Lire::Program qw( :msg :dlf );
use Lire::Firewall qw/ firewall_number2names /;
use Lire::Syslog;

init_dlf_converter( "firewall" );

my $schema      = Lire::DlfSchema::load_schema( "firewall" );
my $dlf_maker   =
  $schema->make_hashref2asciidlf_func( qw/time protocol
                                          from_ip from_port from_host
                                          to_ip to_port to_host rule count msg/);

my $lines      = 0;
my $dlflines   = 0;
my $errorlines = 0;
my $parser     = new Lire::Syslog;

#
# process all line of stdin
#
while (<>) {
    chomp;
    $lines++;

    #
    # skip invalid log entries
    #
    next if $_ !~ /^...\s+\d+\s/;

    eval {
        my $log = $parser->parse( $_ );

        #
        # skip invalid log entries
        #
        return unless $log->{content} =~ /^\[\d+:\d+:\d+\]/;

        my %dlf = ( time => $log->{timestamp} );

        #
        # split the log entries into the necessary fields
        #
        my @chain_infos =
          $log->{content} =~ /^\[(\d+):(\d+):(\d+)\]\s(.+)\s\{(.+)\}\s(.+)\s->\s(.+)\s*$/
          or die "snort lexer failed\n";

        #
        # assign log values to hash
        #
        $dlf{count} = 1;
        $dlf{rule} = $chain_infos[1] . " Rev." . $chain_infos[2];
        $dlf{msg} = $chain_infos[3];
        $dlf{protocol} = $chain_infos[4];
        if ($chain_infos[5] =~ /:/) {
          ($dlf{from_ip}, $dlf{from_port}) = split(/:/, $chain_infos[5]);
        } else {
          $dlf{from_ip} = $chain_infos[5];
          $dlf{from_port} = "-";
        } 
        $dlf{from_host} = $dlf{from_ip};
        if ($chain_infos[6] =~ /:/) {
          ($dlf{to_ip}, $dlf{to_port}) = split(/:/, $chain_infos[6]);
        } else {
          $dlf{to_ip} = $chain_infos[6];
          $dlf{to_port} = "-";
        } 
        $dlf{to_host} = $dlf{to_ip};

        # 
        # convert numbers to names and create dlf-record
        #
        firewall_number2names( \%dlf );
        my $dlf = $dlf_maker->( \%dlf );

        # 
        # print dlf-record to stdout
        #
        print join( " ", @$dlf), "\n";
        $dlflines++;
    };
    if ($@) {
        lr_warn( $@ );
        lr_notice( qq{cannot convert line $. "$_" to firewall dlf, skipping} );
        $errorlines++;
    }
}

end_dlf_converter( $lines, $dlflines, $errorlines );

__END__

=pod

=head1 NAME

snort2dlf - convert Snort logs to firewall DLF

=head1 SYNOPSIS

B<snort2dlf>

=head1 DESCRIPTION

B<snort2dlf> converts Snort logs into firewall DLF format.
Input for this converter is the standard snort logfile.

=head1 EXAMPLES

To process a log as produced by snort:

 $ snort2dlf < snort.log

snort2dlf will be rarely used on its own, but is more likely
called by lr_log2report:

 $ lr_log2report snort < snort.log

=head1 SEE ALSO

The Snort project website at http://www.snort.org/ .

=head1 AUTHOR

Torsten Fellhauer <torsten@fellhauer-web.de> .  Code based upon ipchains2dlf
code by Francis J. Lacoste.

=head1 VERSION

$Id: snort2dlf.in,v 1.7 2006/07/23 13:16:35 vanbaal Exp $

=head1 COPYRIGHT

Copyright (C) 2003 Torsten Fellhauer

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html.

=cut

# Local Variables:
# mode: cperl
# End:
