#! /usr/bin/perl -w

# vim:syntax=perl

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

init_dlf_converter( "firewall" );
my $schema	= Lire::DlfSchema::load_schema( "firewall" );
my $dlf_maker	=
  $schema->make_hashref2asciidlf_func( qw/time rule action protocol
					  from_ip from_port rcv_intf snt_intf
					  to_ip to_port length count /);

my %ipt2dlf = (
	       IN	=> "rcv_intf",
	       OUT	=> "snt_intf",
	       SRC	=> "from_ip",
	       DST	=> "to_ip",
	       SPT	=> "from_port",
	       DPT	=> "to_port",
	       TYPE	=> "from_port",
	       CODE	=> "to_port",
	       LEN	=> "length",
	       PROTO	=> "protocol",
	      );

my $denied_re = qr/deny|denied|drop|reject|unallowed/i;

my %field_re = ();
foreach my $k ( keys %ipt2dlf ) {
    $field_re{$k} = qr/\b$k=(\S*)/;
}

my $lines      = 0;
my $dlflines   = 0;
my $errorlines = 0;
my $parser     = new Lire::Syslog;
while (<>) {
    chomp;
    $lines++;

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

	# Skip non-iptables records
	#
	# The starts of the line is set by the user.
	#
	# We cannot rely on the process name (usually kernel) since
	# this is added by klogd and not by the iptables logging code.
	return unless $log->{content} =~ /IN=\w* OUT=\w*/;

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

	# There is a problem with the IPTable log, there is no real
	# informations on how to determine the reason the packet was
	# logged, i.e. denied or permitted. The user must specify
	# a custom label, we set the action to denied if we find common
	# string in the label.
	($dlf{rule}) = $log->{content} =~ /^(.*?)IN=/;
	$dlf{action} = "denied" if $dlf{rule} =~ /$denied_re/;
	while ( my ( $field, $re ) = each %field_re ) {
	    my ( $value ) = $log->{content} =~ /$re/;
	    ($dlf{$ipt2dlf{$field}}) = $value
	      if defined $value;
	}

	# IPTables will log the following on all packet
	die "iptables lexer failed\n"
	  unless exists $dlf{from_ip} &&
	         exists $dlf{to_ip} &&
	         exists $dlf{length} &&
		 exists $dlf{protocol};

	firewall_number2names( \%dlf );

	my $dlf = $dlf_maker->( \%dlf );

	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

iptables2dlf - convert IP Tables syslog logs to firewall DLF

=head1 SYNOPSIS

B<iptables2dlf> I<file>

=head1 DESCRIPTION

B<iptables2dlf> converts Linux 2.4 packet log into firewall DLF format.

=head1 LIMITATIONS

The netfilter logging modules doesn't log the status of the packet
(drop, accept, reject) like the ipchains logging code. You can specify
a prefix that will be used in the log. This converter will marks the
packet as 'denied' whenever that prefix match (case insensitive) the
following regex: 'denied|deny|drop|reject', other packets will have
'-' as the value of the 'action' field.

So in order for that converter to detect 'denied' packets, you should use
prefix containing one of those substrings.

For example:

 iptables -N lodrop
 iptables -A logdrop -j LOG --log-prefix "Packet-DENY: "
 iptables -A logdrop -j DROP

or other similar prefixes: 'denied: ', 'Packet-REJECT: ', ...

The prefix used will ends up in the 'rule' field of the DLF record.

=head1 SEE ALSO

The Netfilter webpage at http://netfilter.samba.org/ .

=head1 AUTHORS

Francis J. Lacoste <flacoste@logreport.org>

=head1 VERSION

$Id: iptables2dlf.in,v 1.7 2002/08/17 00:11:50 flacoste Exp $

=head1 COPYRIGHT

Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org
 
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 or write to the Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.

=cut

# Local Variables:
# mode: cperl
# End:
