Revision history for Perl extension IPTables::Parse.
+0.9 Sun Feb 26 21:01:45 2012
+ - Applied slightly modified patch from SSIMON to properly pick up usage of
+ state tracking in rule extended information as shown in this bug:
+ https://rt.cpan.org/Ticket/Display.html?id=67372#txn-925687
+ Rule 'extended' hash now includes the 'state' or 'ctstate' key
+ depending on which iptables state tracking module is being used (if
+ any).
+
0.8 Sun Feb 26 14:03:24 2012
- Major update to support ip6tables policies.
- Added test suite script t/basic_tests.pl to exercise major functions for
-IPTables-Parse version 0.8
+IPTables-Parse version 0.9
===========================
The README is used to introduce the module and provide instructions on
#
# Author: Michael Rash (mbr@cipherdyne.org)
#
-# Version: 0.8
+# Version: 0.9
#
##################################################################
#
use warnings;
use vars qw($VERSION);
-$VERSION = '0.8';
+$VERSION = '0.9';
sub new() {
my $class = shift;
my $found_chain = 0;
my @ipt_lines = ();
- ### only used for IPv4 and NAT
+ ### only used for IPv4 + NAT
my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|;
### array of hash refs
'to_port' => '',
'extended' => '',
'state' => '',
+ 'ctstate' => '',
'raw' => $line
);
$rule{'to_ip'} = $1;
$rule{'to_port'} = $2;
}
-
- for my $state_hr (@global_accept_state) {
- next unless $state_hr->{'src'} eq '0.0.0.0/0';
- next unless $state_hr->{'dst'} eq '0.0.0.0/0';
- next unless $state_hr->{'proto'} eq 'all' or
- $state_hr->{'proto'} = $rule{'proto'};
- next unless $state_hr->{'intf_in'} eq '*' or
- $state_hr->{'intf_in'} eq $rule{'intf_in'};
- next unless $state_hr->{'intf_out'} eq '*' or
- $state_hr->{'intf_out'} eq $rule{'intf_out'};
- ### if we make it here, then the state rule
- ### applies to this rule
- $rule{'state'} = $state_hr->{'state'};
- }
}
- if ($rule{'target'} eq 'ACCEPT'
- and $rule{'extended'} =~ m|^state\s+(\S+)|) {
- my $state_str = $1;
- if ($state_str =~ /ESTABLISHED/
- or $state_str =~ /RELATED/) {
-
- push @global_accept_state, {
- 'state' => $state_str,
- 'src' => $rule{'src'},
- 'dst' => $rule{'dst'},
- 'intf_in' => $rule{'intf_in'},
- 'intf_out' => $rule{'intf_out'},
- 'proto' => $rule{'protocol'}
- };
- my %state_hash = ();
- }
+ if ($rule{'extended'} =~ /\bctstate\s+(\S+)/) {
+ $rule{'ctstate'} = $1;
+ } elsif ($rule{'extended'} =~ /\bstate\s+(\S+)/) {
+ $rule{'state'} = $1;
}
}
}
$rule{'to_ip'} = $1;
$rule{'to_port'} = $2;
}
+
+ if ($rule{'extended'} =~ /\bctstate\s+(\S+)/) {
+ $rule{'ctstate'} = $1;
+ } elsif ($rule{'extended'} =~ /\bstate\s+(\S+)/) {
+ $rule{'state'} = $1;
+ }
}
}
}
my $rules_ar = $ipt_obj->chain_rules($table, $chain);
- ### compare raw rules list with parsed chain_rules()
- ### output - basic number check
$executed++;
- if (($#$out_ar - 2) == $#$rules_ar) {
+ my $matched_state = 1;
+ for (my $i=2; $i<=$#$out_ar; $i++) {
+ if ($out_ar->[$i] =~ /\sctstate/) {
+ unless (defined $rules_ar->[$i-2]->{'ctstate'}
+ and $rules_ar->[$i-2]->{'ctstate'}) {
+ $matched_state = 0;
+ last;
+ }
+ } elsif ($out_ar->[$i] =~ /\sstate/) {
+ unless (defined $rules_ar->[$i-2]->{'state'}
+ and $rules_ar->[$i-2]->{'state'}) {
+ $matched_state = 0;
+ last;
+ }
+ }
+ }
+
+ ### compare raw rules list with parsed chain_rules()
+ ### output - basic number check
+ if (($#$out_ar - 2) == $#$rules_ar and $matched_state) {
&logr("pass ($executed)\n");
$passed++;
} else {
&logr("fail ($executed)\n");
- if (($#$out_ar - 2) > $#$rules_ar) {
- &logr(" chain_rules() missed rules.\n");
- } elsif (($#$out_ar - 2) < $#$rules_ar) {
- &logr(" chain_rules() added inappropriate rules.\n");
+ if ($matched_state) {
+ &logr(" chain_rules() missed extended state info.\n");
+ } else {
+ if (($#$out_ar - 2) > $#$rules_ar) {
+ &logr(" chain_rules() missed rules.\n");
+ } elsif (($#$out_ar - 2) < $#$rules_ar) {
+ &logr(" chain_rules() added inappropriate rules.\n");
+ }
}
$failed++;
}