From ca1a5a39e4c5233caa10fb8a28dbba74d49b6192 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 4 Nov 2014 07:44:37 +0100 Subject: [PATCH 1/1] ipset_match: implement simulation of list type ipsets --- src/PVE/FirewallSimulator.pm | 53 ++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/PVE/FirewallSimulator.pm b/src/PVE/FirewallSimulator.pm index 30ae847..4042ace 100644 --- a/src/PVE/FirewallSimulator.pm +++ b/src/PVE/FirewallSimulator.pm @@ -53,21 +53,40 @@ sub nf_dev_match { } sub ipset_match { - my ($ipsetname, $ipset, $ipaddr) = @_; + my ($ipset_ruleset, $ipsetname, $ipaddr) = @_; + + my $ipset = $ipset_ruleset->{$ipsetname}; + die "no such ipset '$ipsetname'" if !$ipset; my $ip = Net::IP->new($ipaddr); - foreach my $entry (@$ipset) { - next if $entry =~ m/^create/; # simply ignore - if ($entry =~ m/add \S+ (\S+)$/) { - my $test = Net::IP->new($1); - if ($test->overlaps($ip)) { - add_trace("IPSET $ipsetname match $ipaddr\n"); - return 1; + my $first = $ipset->[0]; + if ($first =~ m/^create\s+\S+\s+list:/) { + foreach my $entry (@$ipset) { + next if $entry =~ m/^create/; # simply ignore + if ($entry =~ m/add \S+ (\S+)$/) { + return 1 if ipset_match($ipset_ruleset, $1, $ipaddr); + } else { + die "implement me"; + } + } + return 0; + } elsif ($first =~ m/^create\s+\S+\s+hash:net/) { + foreach my $entry (@$ipset) { + next if $entry =~ m/^create/; # simply ignore + if ($entry =~ m/add \S+ (\S+)$/) { + my $test = Net::IP->new($1); + if ($test->overlaps($ip)) { + add_trace("IPSET $ipsetname match $ipaddr\n"); + return 1; + } + } else { + die "implement me"; } - } else { - die "implement me"; } + return 0; + } else { + die "unknown ipset type '$first' - not implemented\n"; } return 0; @@ -154,21 +173,19 @@ sub rule_match { if ($rule =~ s/^-m set (!\s+)?--match-set (\S+) src\s*//) { die "missing source" if !$pkg->{source}; my $neg = $1; - my $ipset = $ipset_ruleset->{$2}; - die "no such ip set '$2'" if !$ipset; + my $ipset_name = $2; if ($neg) { - return undef if ipset_match($1, $ipset, $pkg->{source}); + return undef if ipset_match($ipset_ruleset, $ipset_name, $pkg->{source}); } else { - return undef if !ipset_match($1, $ipset, $pkg->{source}); + return undef if !ipset_match($ipset_ruleset, $ipset_name, $pkg->{source}); } next; } if ($rule =~ s/^-m set --match-set (\S+) dst\s*//) { die "missing destination" if !$pkg->{dest}; - my $ipset = $ipset_ruleset->{$1}; - die "no such ip set '$1'" if !$ipset; - return undef if !ipset_match($1, $ipset, $pkg->{dest}); + my $ipset_name = $1; + return undef if !ipset_match($ipset_ruleset, $ipset_name, $pkg->{dest}); next; } @@ -301,6 +318,8 @@ sub copy_packet { sub route_packet { my ($ruleset, $ipset_ruleset, $pkg, $from_info, $target, $start_state) = @_; + $pkg->{ipversion} = 4; # fixme: allow ipv6 + my $route_state = $start_state; my $physdev_in; -- 2.39.2