#
# $Id: Netfilter.pm,v 1.1 2002/03/05 23:44:51 fpmip Exp $
#

# Author : Tycho Fruru <tycho@fruru.com>

# Copyright (C) 2001 Tycho Fruru <tycho@fruru.com>
# Copyright (C) 2001 Conostix S.A. Luxembourg - Tycho Fruru <tycho@conostix.com>

# 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#

package IPFC::Parse::Event::Netfilter;

use strict;
use warnings;
use IPFC::Log;

BEGIN {
	use Exporter   ();
        our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);

        # set the version for version checking
        $VERSION = do { my @r = (q$Revision: 1.1 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker

        @ISA         = qw(Exporter);
        @EXPORT      = qw( );
        %EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
        @EXPORT_OK   = qw( );
}
our @EXPORT_OK;

sub parse($$$) {
	shift; # current class
	my $dbh = shift;
	my $entry = shift;
	my $r_sql_hash = shift;
	
	# make local copies so that we don't pollute the global variables
	my %sql_hash = %{$r_sql_hash};
	
	my $rc = 1;
	
	my $netfilter_line = $entry->{'content'}->[0]->{'netfilter-line'};
	if (!defined($netfilter_line)) { 
		warn "There is no netfilter-line entry !";
		return 0;
	}
	
	if (ref($netfilter_line) eq "ARRAY") {
		my $index = 0;
		my $rc = 1;
		
		my $start_time = time();
		my $elapsed_time;
		my $speed;
		
		while (defined($netfilter_line->[$index]) && $rc==1) {
			
#			if ($index % 1000 == 0) { 
#				$elapsed_time = time()-$start_time;
#				if ($index != 0) { 
#					$speed = int($index / $elapsed_time);
#				} else {
#					$speed = 0;
#				}
# 				IPFC::Log::logger(3,"$index entries processed in $elapsed_time seconds, $speed per second.\n");
#			}
		
		 	my %netfilter_sql_hash = %sql_hash;
			
			my $decoded_netfilter_line = decode_entry($netfilter_line->[$index]);
			
# now we'll parse the decoded_netfilter_line ...

			if ($decoded_netfilter_line =~ /IN=.* OUT=.* /) {
				# it's not a netfilter line !
				IPFC::Log::logger(2,"Not a netfilter line on line $index ...");
				$index++;
				next;
			}				

			$decoded_netfilter_line =~ /^.* kernel: (.*)IN=(.*) OUT=(.*) (.*)$/ ;
			
			$netfilter_sql_hash{'prefix'} = $1;
			$netfilter_sql_hash{'in_interface'} = $2;
			$netfilter_sql_hash{'out_interface'} = $3;
			
			$decoded_netfilter_line = $4;
			
			if ($decoded_netfilter_line =~ /^MAC=([^ ]*) (.*) $/) {
				$netfilter_sql_hash{'in_mac_address'} = $1;
				$decoded_netfilter_line = $2;
			}
			
			$decoded_netfilter_line =~ /^SRC=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) DST=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) (.*)$/;
			
			$netfilter_sql_hash{'src_host'} = $1;
			$netfilter_sql_hash{'dst_host'} = $2;
			$decoded_netfilter_line = $3;
			
			$decoded_netfilter_line =~ /^LEN=([0-9]+) TOS=0x([0-9A-F][0-9A-F]) PREC=0x([0-9A-F][0-9A-F]) TTL=([0-9]+) ID=([0-9]+) (.*)$/;
			
			$netfilter_sql_hash{'length'} = $1;
			$netfilter_sql_hash{'ip_tos'} = $2;
			$netfilter_sql_hash{'ip_prec'} = $3;
			$netfilter_sql_hash{'ip_ttl'} = $4;
			$netfilter_sql_hash{'ip_id'} = $5;
			$decoded_netfilter_line = $6;
			
			if ($decoded_netfilter_line =~ /^CE (.*)$/) {
				$netfilter_sql_hash{'ip_ce'} = 't';
				$decoded_netfilter_line = $1;
			}
			
			if ($decoded_netfilter_line =~ /^DF (.*)$/) {
				$netfilter_sql_hash{'ip_df'} = 't';
				$decoded_netfilter_line = $1;
			}
			
			if ($decoded_netfilter_line =~ /^MF (.*)$/) {
				$netfilter_sql_hash{'ip_mf'} = 't';
				$decoded_netfilter_line = $1;
			}
			
			if ($decoded_netfilter_line =~ /^FRAG:([0-9]+) (.*)$/) {
				$netfilter_sql_hash{'ip_frag'} = $1;
				$decoded_netfilter_line = $2;
			}
			
			if ($decoded_netfilter_line =~ /^OPT\((.+)\) (.*)$/) {
				$netfilter_sql_hash{'ip_opt'} = $1;
				$decoded_netfilter_line = $2;
			}
			
			if ($decoded_netfilter_line =~ /^PROTO=TCP (.*)$/) {
				$netfilter_sql_hash{'ip_proto'} = 6; # IP protocol 6 = TCP
				$decoded_netfilter_line = $1;
				
				if ($decoded_netfilter_line =~ /^INCOMPLETE \[([0-9]+) bytes\]/) {
					$netfilter_sql_hash{'incomplete_hdr'} = 't';
				} else {
					$netfilter_sql_hash{'incomplete_hdr'} = 'f';
				}
				
				if ($decoded_netfilter_line =~ /^SPT=([0-9]+) DPT=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'src_port'} = $1;
					$netfilter_sql_hash{'dst_port'} = $2;
					$decoded_netfilter_line = $3;
				}
				
				if ($decoded_netfilter_line =~ /^SEQ=([0-9]+) ACK=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'tcp_seq'} = $1;
					$netfilter_sql_hash{'tcp_ackseq'} = $2;
					$decoded_netfilter_line = $3;
				}
				
				if ($decoded_netfilter_line =~ /^WINDOW=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'tcp_window'} = $1;
					$decoded_netfilter_line = $2;
				}
				
				if ($decoded_netfilter_line =~ /^RES=0x([0-9A-F]+) (.*)$/) {
					$decoded_netfilter_line = $2;
				}
				
				if ($decoded_netfilter_line =~ /^CWR (.*)$/) {
					$netfilter_sql_hash{'tcp_cwr'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_cwr'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^ECE (.*)$/) {
					$netfilter_sql_hash{'tcp_ece'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_ece'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^URG (.*)$/) {
					$netfilter_sql_hash{'tcp_urg'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_urg'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^ACK (.*)$/) {
					$netfilter_sql_hash{'tcp_ack'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_ack'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^PSH (.*)$/) {
					$netfilter_sql_hash{'tcp_psh'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_psh'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^RST (.*)$/) {
					$netfilter_sql_hash{'tcp_rst'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_rst'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^SYN (.*)$/) {
					$netfilter_sql_hash{'tcp_syn'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_syn'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^FIN (.*)$/) {
					$netfilter_sql_hash{'tcp_fin'} = 't';
					$decoded_netfilter_line = $1;
				} else {
					$netfilter_sql_hash{'tcp_fin'} = 'f';
					$decoded_netfilter_line = $1;
				}
				
				if ($decoded_netfilter_line =~ /^URGP=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'tcp_urgp'} = $1;
					$decoded_netfilter_line = $2;
				}
				
				if ($decoded_netfilter_line =~ /^OPT=([^)]+) (.*)$/) {
					$netfilter_sql_hash{'tcp_opt'} = $1;
					$decoded_netfilter_line = $2;
				}
				
			} elsif ($decoded_netfilter_line =~ /^PROTO=UDP (.*)$/) {
				$netfilter_sql_hash{'ip_proto'} = 17;
				$decoded_netfilter_line = $1;
				
				if ($decoded_netfilter_line =~ /^INCOMPLETE \[([0-9]+) bytes\]/) {
					$netfilter_sql_hash{'incomplete_hdr'} = 't';
				} else {
					$netfilter_sql_hash{'incomplete_hdr'} = 'f';
				}
				
				if ($decoded_netfilter_line =~ /^SPT=([0-9]+) DPT=([0-9]+) LEN=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'src_port'} = $1;
					$netfilter_sql_hash{'dst_port'} = $2;
					$netfilter_sql_hash{'udp_length'} = $3;
					$decoded_netfilter_line = $4;
				}
			} elsif ($decoded_netfilter_line =~ /^PROTO=ICMP (.*)$/) {
				$netfilter_sql_hash{'ip_proto'} = 1;
				$decoded_netfilter_line = $1;
								
				if ($decoded_netfilter_line =~ /^INCOMPLETE \[([0-9]+) bytes\]/) {
					$netfilter_sql_hash{'incomplete_hdr'} = 't';
				} else {
					$netfilter_sql_hash{'incomplete_hdr'} = 'f';
				}
				
				if ($decoded_netfilter_line =~ /^TYPE=([0-9]+) CODE=([0-9]+) (.*)$/) {
					$netfilter_sql_hash{'icmp_type'} = $1;
					$netfilter_sql_hash{'icmp_code'} = $2;
					$decoded_netfilter_line = $3;
				}
			} elsif ($decoded_netfilter_line =~ /^PROTO=({ESP|AH}) (.*)$/) {
				if ($1 eq 'ESP') {
					$netfilter_sql_hash{'ip_proto'} = 50;
				} else {
					$netfilter_sql_hash{'ip_proto'} = 51;
				}
				
				$decoded_netfilter_line = $2;
				
				if ($decoded_netfilter_line =~ /^INCOMPLETE \[([0-9]+) bytes\]/) {
					$netfilter_sql_hash{'incomplete_hdr'} = 't';
				} else {
					$netfilter_sql_hash{'incomplete_hdr'} = 'f';
				}
				
				if ($decoded_netfilter_line =~ /^SPI=0x([0-9A-F]+) (.*)$/) {
					$netfilter_sql_hash{'ipsec_spi'} = $1;
					$decoded_netfilter_line = $2;
				}
			} elsif ($decoded_netfilter_line =~ /^PROTO=([0-9]+)/ ) {
				$netfilter_sql_hash{'ip_proto'} = $1;
			}
			
			
			
				
			$rc = IPFC::DB::Event::put_event($dbh,\%netfilter_sql_hash);
			$index++;
		}
	} else { 
		warn "There are no netfilter-lines in this file !"; 
		$rc = 0; 
	}
			
	IPFC::Log::logger(5,"End of netfilter_log_1\n");
	
	return $rc; # 1 is ok, 0 is not ok
}

sub decode_netfilter($) {
# returns a hash which contains as keys the keywords encountered in the first parameter, as values it contains
# the values of the different code-words

	my $line = shift;
	my %decoded;
	
}


return 1;
