summaryrefslogtreecommitdiff
path: root/lib/Vyatta/IpTables/IpSet.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Vyatta/IpTables/IpSet.pm')
-rwxr-xr-xlib/Vyatta/IpTables/IpSet.pm412
1 files changed, 208 insertions, 204 deletions
diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm
index 5222edc..37bbb37 100755
--- a/lib/Vyatta/IpTables/IpSet.pm
+++ b/lib/Vyatta/IpTables/IpSet.pm
@@ -1,24 +1,24 @@
#
# Module: IpSet.pm
-#
+#
# **** License ****
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
-#
+#
# 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.
-#
+#
# This code was originally developed by Vyatta, Inc.
# Portions created by Vyatta are Copyright (C) 2009-2010 Vyatta, Inc.
# All Rights Reserved.
-#
+#
# Author: Stig Thormodsrud
# Date: January 2009
# Description: vyatta interface to ipset
-#
+#
# **** End License ****
#
@@ -48,7 +48,7 @@ our %grouptype_hash = (
my $logger = 'logger -t IpSet.pm -p local0.warn --';
-# Currently we restrict an address range to a /24 even
+# Currently we restrict an address range to a /24 even
# though ipset would support a /16. The main reason is
# due to the long time it takes to make that many calls
# to add each individual member to the set.
@@ -67,17 +67,15 @@ $SIG{'INT'} = 'INT_handler';
sub new {
my ($that, $name, $type) = @_;
- my $class = ref ($that) || $that;
- my $self = {
- %fields,
- };
+ my $class = ref($that) || $that;
+ my $self = {%fields,};
if ($name =~ m/^!/) {
- $self->{_negate} = 1;
- $name =~ s/^!(.*)$/$1/;
+ $self->{_negate} = 1;
+ $name =~ s/^!(.*)$/$1/;
}
$self->{_name} = $name;
$self->{_type} = $type;
-
+
bless $self, $class;
return $self;
}
@@ -94,8 +92,8 @@ sub run_cmd {
my $rc = system("sudo $cmd");
if (defined $self->{_debug}) {
- my $func = (caller(1))[3];
- system("$logger [$func] [$cmd] = [$rc]");
+ my $func = (caller(1))[3];
+ system("$logger [$func] [$cmd] = [$rc]");
}
return $rc;
}
@@ -104,12 +102,12 @@ sub exists {
my ($self) = @_;
return 1 if defined $self->{_exists};
- return 0 if ! defined $self->{_name};
+ return 0 if !defined $self->{_name};
my $cmd = "ipset -L $self->{_name} > /dev/null 2>&1";
my $rc = $self->run_cmd($cmd);
if ($rc eq 0) {
- $self->{_exists} = 1;
- $self->get_type() if ! defined $self->{_type};
+ $self->{_exists} = 1;
+ $self->get_type() if !defined $self->{_type};
}
return $rc ? 0 : 1;
}
@@ -118,21 +116,21 @@ sub get_type {
my ($self) = @_;
return $self->{_type} if defined $self->{_type};
- return if ! $self->exists();
+ return if !$self->exists();
my @lines = `ipset -L $self->{_name}`;
my $type;
foreach my $line (@lines) {
- if ($line =~ /^Type:\s+([\w:]+)$/) {
- $type = $1;
- last;
- }
+ if ($line =~ /^Type:\s+([\w:]+)$/) {
+ $type = $1;
+ last;
+ }
}
- return if ! defined $type;
+ return if !defined $type;
foreach my $vtype (keys(%grouptype_hash)) {
- if ($grouptype_hash{$vtype} eq $type) {
- $self->{_type} = $vtype;
- last;
- }
+ if ($grouptype_hash{$vtype} eq $type) {
+ $self->{_type} = $vtype;
+ last;
+ }
}
return $self->{_type};
}
@@ -147,54 +145,54 @@ sub natural_order {
my ($a, $b) = @_;
my @a = alphanum_split($a);
my @b = alphanum_split($b);
-
+
while (@a && @b) {
- my $a_seg = shift @a;
- my $b_seg = shift @b;
- my $val;
- if (($a_seg =~ /\d/) && ($b_seg =~ /\d/)) {
- $val = $a_seg <=> $b_seg;
- } else {
- $val = $a_seg cmp $b_seg;
- }
- if ($val != 0) {
- return $val;
- }
+ my $a_seg = shift @a;
+ my $b_seg = shift @b;
+ my $val;
+ if (($a_seg =~ /\d/) && ($b_seg =~ /\d/)) {
+ $val = $a_seg <=> $b_seg;
+ } else {
+ $val = $a_seg cmp $b_seg;
+ }
+ if ($val != 0) {
+ return $val;
+ }
}
return @a <=> @b;
}
sub get_members {
my ($self) = @_;
-
+
my @members = ();
- return @members if ! $self->exists();
+ return @members if !$self->exists();
my @lines = `ipset -L $self->{_name} -s`;
foreach my $line (@lines) {
- push @members, $line if $line =~ /^\d/;
+ push @members, $line if $line =~ /^\d/;
}
if ($self->{_type} ne 'port') {
- @members = sort { natural_order($a,$b) } @members;
+ @members = sort {natural_order($a,$b)} @members;
}
return @members;
}
sub create {
my ($self) = @_;
-
- return "Error: undefined group name" if ! defined $self->{_name};
- return "Error: undefined group type" if ! defined $self->{_type};
+
+ return "Error: undefined group name" if !defined $self->{_name};
+ return "Error: undefined group type" if !defined $self->{_type};
return if $self->exists(); # treat as nop if already exists
my $ipset_param = $grouptype_hash{$self->{_type}};
- return "Error: invalid group type\n" if ! defined $ipset_param;
+ return "Error: invalid group type\n" if !defined $ipset_param;
if ($self->{_type} eq 'port') {
- $ipset_param .= ' --from 1 --to 65535';
- }
+ $ipset_param .= ' --from 1 --to 65535';
+ }
- my $cmd = "ipset -N $self->{_name} $ipset_param";
+ my $cmd = "ipset -N $self->{_name} $ipset_param";
my $rc = $self->run_cmd($cmd);
return "Error: call to ipset failed [$rc]" if $rc;
return; # undef
@@ -203,45 +201,47 @@ sub create {
sub references {
my ($self) = @_;
- return 0 if ! $self->exists();
+ return 0 if !$self->exists();
my @lines = `ipset -L $self->{_name}`;
foreach my $line (@lines) {
- if ($line =~ /^References:\s+(\d+)$/) {
- return $1;
- }
+ if ($line =~ /^References:\s+(\d+)$/) {
+ return $1;
+ }
}
return 0;
}
sub flush {
- my ($self) = @_;
- my $cmd = "ipset flush $self->{_name}";
- my $rc = $self->run_cmd($cmd);
- return "Error: call to ipset failed [$rc]" if $rc;
- return;
+ my ($self) = @_;
+ my $cmd = "ipset flush $self->{_name}";
+ my $rc = $self->run_cmd($cmd);
+ return "Error: call to ipset failed [$rc]" if $rc;
+ return;
}
sub rebuild_ipset() {
- my ($self) = @_;
- my $name = $self->{_name};
- my $type = $self->{_type};
- my $config = new Vyatta::Config;
-
- my @members = $config->returnOrigValues("firewall group $type-group $name $type");
- # go through the firewall group config with this name,
- my $member;
- foreach $member (@members) {
- $self->add_member($member, $name);
- }
+ my ($self) = @_;
+ my $name = $self->{_name};
+ my $type = $self->{_type};
+ my $config = new Vyatta::Config;
+
+ my @members = $config->returnOrigValues("firewall group $type-group $name $type");
+
+ # go through the firewall group config with this name,
+ my $member;
+ foreach $member (@members) {
+ $self->add_member($member, $name);
+ }
}
sub reset_ipset_named {
- my ($self) = @_;
- my $name = $self->{_name};
- # flush the ipset group first, then re-build the group from configuration
- $self->flush();
-
- $self->rebuild_ipset();
+ my ($self) = @_;
+ my $name = $self->{_name};
+
+ # flush the ipset group first, then re-build the group from configuration
+ $self->flush();
+
+ $self->rebuild_ipset();
}
sub reset_ipset_all {
@@ -249,57 +249,61 @@ sub reset_ipset_all {
my @pgroups = $config->listOrigNodes("firewall group port-group");
my @adgroups = $config->listOrigNodes("firewall group address-group");
my @nwgroups = $config->listOrigNodes("firewall group network-group");
- my $group;
+ my $group;
foreach $group (@pgroups) {
- my $grp = new Vyatta::IpTables::IpSet($group, "port");
- $grp->reset_ipset_named();
+ my $grp = new Vyatta::IpTables::IpSet($group, "port");
+ $grp->reset_ipset_named();
}
foreach $group (@adgroups) {
- my $grp = new Vyatta::IpTables::IpSet($group, "address");
- $grp->reset_ipset_named();
+ my $grp = new Vyatta::IpTables::IpSet($group, "address");
+ $grp->reset_ipset_named();
}
foreach $group (@nwgroups) {
- my $grp = new Vyatta::IpTables::IpSet($group, "network");
- $grp->reset_ipset_named();
+ my $grp = new Vyatta::IpTables::IpSet($group, "network");
+ $grp->reset_ipset_named();
}
}
sub reset_ipset {
- # main function to do the reset operation
- my ($self) = @_;
- my $name = $self->{_name};
-
- my $lockcmd = "touch $lockfile";
- my $unlockcmd = "rm -f $lockfile";
- $self->run_cmd($lockcmd);
-
- # reset one rule or all?
- if ($name eq 'all') {
- $self->reset_ipset_all();
- } else {
- $self->reset_ipset_named();
- }
- my $rc = $self->run_cmd($unlockcmd);
- return "Error: call to ipset failed [$rc]" if $rc;
- return; # undef
+
+ # main function to do the reset operation
+ my ($self) = @_;
+ my $name = $self->{_name};
+
+ my $lockcmd = "touch $lockfile";
+ my $unlockcmd = "rm -f $lockfile";
+ $self->run_cmd($lockcmd);
+
+ # reset one rule or all?
+ if ($name eq 'all') {
+ $self->reset_ipset_all();
+ } else {
+ $self->reset_ipset_named();
+ }
+ my $rc = $self->run_cmd($unlockcmd);
+ return "Error: call to ipset failed [$rc]" if $rc;
+ return; # undef
}
sub delete {
my ($self) = @_;
- return "Error: undefined group name" if ! defined $self->{_name};
+ return "Error: undefined group name" if !defined $self->{_name};
return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists();
my $refs = $self->references();
if ($refs > 0) {
- # still in use
- if (scalar($self->get_firewall_references(1)) > 0) {
- # still referenced by config
- return "Error: group [$self->{_name}] still in use.\n";
- }
- # not referenced by config => simultaneous deletes. just do flush.
- return $self->flush();
+
+ # still in use
+ if (scalar($self->get_firewall_references(1)) > 0) {
+
+ # still referenced by config
+ return "Error: group [$self->{_name}] still in use.\n";
+ }
+
+ # not referenced by config => simultaneous deletes. just do flush.
+ return $self->flush();
}
my $cmd = "ipset -X $self->{_name}";
@@ -312,10 +316,10 @@ sub check_member_address {
my $member = shift;
if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) {
- return "Error: [$member] isn't valid IPv4 address\n";
+ return "Error: [$member] isn't valid IPv4 address\n";
}
if ($member eq '0.0.0.0') {
- return "Error: zero IP address not valid in address-group\n";
+ return "Error: zero IP address not valid in address-group\n";
}
return;
}
@@ -323,8 +327,8 @@ sub check_member_address {
sub check_member {
my ($self, $member) = @_;
- return "Error: undefined group name" if ! defined $self->{_name};
- return "Error: undefined group type" if ! defined $self->{_type};
+ return "Error: undefined group name" if !defined $self->{_name};
+ return "Error: undefined group type" if !defined $self->{_type};
# We can't call $self->member_exists() here since this is a
# syntax check and the group may not have been created yet
@@ -332,72 +336,72 @@ sub check_member {
# exists check to $self->add_member().
if ($self->{_type} eq 'address') {
- if ($member =~ /^([^-]+)-([^-]+)$/) {
- foreach my $address ($1, $2) {
- my $rc = check_member_address($address);
- return $rc if defined $rc;
- }
- my $start_ip = new NetAddr::IP($1);
- my $stop_ip = new NetAddr::IP($2);
- if ($stop_ip <= $start_ip) {
- return "Error: $1 must be less than $2\n";
- }
- my $start_net = new NetAddr::IP("$1/$addr_range_mask");
- if (! $start_net->contains($stop_ip)) {
- return "Error: address range must be within /$addr_range_mask\n";
- }
-
- } else {
- my $rc = check_member_address($member);
- return $rc if defined $rc;
- }
+ if ($member =~ /^([^-]+)-([^-]+)$/) {
+ foreach my $address ($1, $2) {
+ my $rc = check_member_address($address);
+ return $rc if defined $rc;
+ }
+ my $start_ip = new NetAddr::IP($1);
+ my $stop_ip = new NetAddr::IP($2);
+ if ($stop_ip <= $start_ip) {
+ return "Error: $1 must be less than $2\n";
+ }
+ my $start_net = new NetAddr::IP("$1/$addr_range_mask");
+ if (!$start_net->contains($stop_ip)) {
+ return "Error: address range must be within /$addr_range_mask\n";
+ }
+
+ } else {
+ my $rc = check_member_address($member);
+ return $rc if defined $rc;
+ }
} elsif ($self->{_type} eq 'network') {
- if (!Vyatta::TypeChecker::validateType('ipv4net', $member, 1)) {
- return "Error: [$member] isn't a valid IPv4 network\n";
- }
- if ($member =~ /([\d.]+)\/(\d+)/) {
- my ($net, $mask) = ($1, $2);
- return "Error: zero net invalid in network-group\n"
- if $net eq '0.0.0.0';
- return "Error: invalid mask [$mask] - must be between 1-31\n"
- if $mask < 1 or $mask > 31;
- } else {
- return "Error: Invalid network group [$member]\n";
- }
+ if (!Vyatta::TypeChecker::validateType('ipv4net', $member, 1)) {
+ return "Error: [$member] isn't a valid IPv4 network\n";
+ }
+ if ($member =~ /([\d.]+)\/(\d+)/) {
+ my ($net, $mask) = ($1, $2);
+ return "Error: zero net invalid in network-group\n"
+ if $net eq '0.0.0.0';
+ return "Error: invalid mask [$mask] - must be between 1-31\n"
+ if $mask < 1 or $mask > 31;
+ } else {
+ return "Error: Invalid network group [$member]\n";
+ }
} elsif ($self->{_type} eq 'port') {
- my ($success, $err) = (undef, "invalid port [$member]");
- if ($member =~ /^(\d+)-(\d+)$/) {
- ($success, $err) = Vyatta::Misc::isValidPortRange($member, '-');
- } elsif ($member =~ /^\d/) {
- ($success, $err) = Vyatta::Misc::isValidPortNumber($member);
- } else {
- ($success, $err) = Vyatta::Misc::isValidPortName($member);
- }
- return "Error: $err\n" if defined $err;
+ my ($success, $err) = (undef, "invalid port [$member]");
+ if ($member =~ /^(\d+)-(\d+)$/) {
+ ($success, $err) = Vyatta::Misc::isValidPortRange($member, '-');
+ } elsif ($member =~ /^\d/) {
+ ($success, $err) = Vyatta::Misc::isValidPortNumber($member);
+ } else {
+ ($success, $err) = Vyatta::Misc::isValidPortName($member);
+ }
+ return "Error: $err\n" if defined $err;
} else {
- return "Error: invalid set type [$self->{_type}]";
+ return "Error: invalid set type [$self->{_type}]";
}
- return; #undef
+ return; #undef
}
sub member_exists {
my ($self, $member) = @_;
-
+
my $cmd = "ipset -T $self->{_name} $member -q";
my $rc = $self->run_cmd($cmd);
- return $rc ? 0 : 1;
+ return $rc ? 0 : 1;
}
sub add_member {
my ($self, $member, $alias, $hyphenated_port) = @_;
- return "Error: undefined group name" if ! defined $self->{_name};
+ return "Error: undefined group name" if !defined $self->{_name};
return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists();
if ($self->member_exists($member)) {
my $set_name = $alias;
- $set_name = $self->{_name} if ! defined $set_name;
- return "Error: member [$member] already exists in [$set_name]\n";
+ $set_name = $self->{_name} if !defined $set_name;
+ return "Error: member [$member] already exists in [$set_name]\n";
}
my $cmd = "ipset -A $self->{_name} $member";
my $rc = $self->run_cmd($cmd);
@@ -406,21 +410,21 @@ sub add_member {
}
sub delete_member_range {
- my ($self, $start, $stop) = @_;
-
+ my ($self, $start, $stop) = @_;
+
if ($self->{_type} eq 'port') {
- foreach my $member ($start .. $stop) {
- my $rc = $self->delete_member($member);
- return $rc if defined $rc;
- }
+ foreach my $member ($start .. $stop) {
+ my $rc = $self->delete_member($member);
+ return $rc if defined $rc;
+ }
} elsif ($self->{_type} eq 'address') {
- my $start_ip = new NetAddr::IP("$start/$addr_range_mask");
- my $stop_ip = new NetAddr::IP("$stop/$addr_range_mask");
- for (; $start_ip <= $stop_ip; $start_ip++) {
- my $rc = $self->delete_member($start_ip->addr());
- return $rc if defined $rc;
+ my $start_ip = new NetAddr::IP("$start/$addr_range_mask");
+ my $stop_ip = new NetAddr::IP("$stop/$addr_range_mask");
+ for (; $start_ip <= $stop_ip; $start_ip++) {
+ my $rc = $self->delete_member($start_ip->addr());
+ return $rc if defined $rc;
last if $start_ip->cidr() eq $start_ip->broadcast();
- }
+ }
}
return;
}
@@ -428,17 +432,17 @@ sub delete_member_range {
sub delete_member {
my ($self, $member, $hyphenated_port) = @_;
- return "Error: undefined group name" if ! defined $self->{_name};
+ return "Error: undefined group name" if !defined $self->{_name};
return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists();
# service name or port name may contain a hyphen, which needs to be escaped
# using square brackets in ipset, to avoid confusion with port ranges
if (($member =~ /^([^-]+)-([^-]+)$/) and ((defined($hyphenated_port)) and ($hyphenated_port eq 'false'))) {
- return $self->delete_member_range($1, $2);
+ return $self->delete_member_range($1, $2);
}
if (!$self->member_exists($member)) {
- return "Error: member [$member] doesn't exists in [$self->{_name}]\n";
+ return "Error: member [$member] doesn't exists in [$self->{_name}]\n";
}
my $cmd = "ipset -D $self->{_name} $member";
my $rc = $self->run_cmd($cmd);
@@ -449,10 +453,10 @@ sub delete_member {
sub get_description {
my ($self) = @_;
- return if ! $self->exists();
+ return if !$self->exists();
my $config = new Vyatta::Config;
my $group_type = "$self->{_type}-group";
- $config->setLevel("firewall group $group_type $self->{_name}");
+ $config->setLevel("firewall group $group_type $self->{_name}");
return $config->returnOrigValue('description');
}
@@ -463,29 +467,29 @@ sub get_firewall_references {
($lfunc, $vfunc) = qw(listNodes returnValue);
}
my @fw_refs = ();
- return @fw_refs if ! $self->exists();
+ return @fw_refs if !$self->exists();
my $config = new Vyatta::Config;
foreach my $tree ('name', 'modify') {
- my $path = "firewall $tree ";
- $config->setLevel($path);
- my @names = $config->$lfunc();
- foreach my $name (@names) {
- my $name_path = "$path $name rule ";
- $config->setLevel($name_path);
- my @rules = $config->$lfunc();
- foreach my $rule (@rules) {
- foreach my $dir ('source', 'destination') {
- my $rule_path = "$name_path $rule $dir group";
- $config->setLevel($rule_path);
- my $group_type = "$self->{_type}-group";
- my $value = $config->$vfunc($group_type);
- $value =~ s/^!(.*)$/$1/ if defined $value;
- if (defined $value and $self->{_name} eq $value) {
- push @fw_refs, "$name-$rule-$dir";
- }
- } # foreach $dir
- } # foreach $rule
- } # foreach $name
+ my $path = "firewall $tree ";
+ $config->setLevel($path);
+ my @names = $config->$lfunc();
+ foreach my $name (@names) {
+ my $name_path = "$path $name rule ";
+ $config->setLevel($name_path);
+ my @rules = $config->$lfunc();
+ foreach my $rule (@rules) {
+ foreach my $dir ('source', 'destination') {
+ my $rule_path = "$name_path $rule $dir group";
+ $config->setLevel($rule_path);
+ my $group_type = "$self->{_type}-group";
+ my $value = $config->$vfunc($group_type);
+ $value =~ s/^!(.*)$/$1/ if defined $value;
+ if (defined $value and $self->{_name} eq $value) {
+ push @fw_refs, "$name-$rule-$dir";
+ }
+ } # foreach $dir
+ } # foreach $rule
+ } # foreach $name
} # foreach $tree
return @fw_refs;
}
@@ -493,10 +497,10 @@ sub get_firewall_references {
sub rule {
my ($self, $direction) = @_;
- if (! $self->exists()) {
- my $name = $self->{_name};
- $name = 'undefined' if ! defined $name;
- return (undef, "Undefined group [$name]");
+ if (!$self->exists()) {
+ my $name = $self->{_name};
+ $name = 'undefined' if !defined $name;
+ return (undef, "Undefined group [$name]");
}
my $srcdst;
@@ -504,10 +508,10 @@ sub rule {
$srcdst = 'src' if $direction eq 'source';
$srcdst = 'dst' if $direction eq 'destination';
- return (undef, "Invalid direction [$direction]") if ! defined $srcdst;
+ return (undef, "Invalid direction [$direction]") if !defined $srcdst;
my $opt = '';
$opt = '!' if $self->{_negate};
- return (" -m set $opt --match-set $grp $srcdst ", );
+ return (" -m set $opt --match-set $grp $srcdst ",);
}
1;